Reputation: 504
I am trying to define an abstract class that has operators to compare two instances of the class. When concretizing the class, however, I want the methods to only compare instances of the same type. Something like this
abstract class ComparableSuper{
def <(other: ComparableSuper): Boolean
def <=(other: ComparableSuper): Boolean
def >(other: ComparableSuper): Boolean
def >=(other: ComparableSuper): Boolean
}
class Comparable (val a: Int) extends ComparableSuper {
def <(other: Comparable): Boolean = this.a < other.a
def >(other: Comparable): Boolean = this.a > other.a
def <=(other: Comparable): Boolean = this.a <= other.a
def >=(other: Comparable): Boolean = this.a >= other.a
}
Of course this code does not compile because I am not overriding the methods in the abstract class. If I change Comparable to ComparableSuper in the methods, however, I won't have the assurance that the field a is there.
Is there a way I could specify the type of the class in the method signature?
Thanks in advance.
Upvotes: 1
Views: 194
Reputation: 139058
In this case using math.Ordered
or math.Ordering
is a better idea, but if you do need this pattern, you can use F-bounded polymorphism:
trait Foo[A <: Foo[A]] {
def f(that: A): Int
}
class Bar(val x: Int) extends Foo[Bar] {
def f(that: Bar) = this.x - that.x
}
There's a bit of syntactic overhead involved in parametrizing the supertype, but it allows you to have methods that require an instance of the same subclass.
Upvotes: 2
Reputation: 26586
I highly recommend you to look at Ordering type class.
I find, that type-class approach to this problem is much better than Comaprable
way of doing it (where objects, that you want to compare, actually extend Comparable
).
With type-class approach you will also give you more type-safety and flexibility. You can actually define Ordering
instances for existing classes (classes that you can't control and change).
Ordering
can be a little bit clumsy to use, but Ordered
has implicits that will allow you to write code like this:
import math.Ordered._
def isGreater[T : Ordering](a: T, b: T) = a > b
So you even don't compromise convenience. (by the way, Ordered
is equivalent to Java's Comparable
)
Upvotes: 3