I'm creating some parameterized classes C[T] and I want to make some requirements of the characteristics of the type T to be able to be a parameter of my class. It would be simple if I just wanted to say that T inherited from traits or classes (as we do with Ordering). But I want it to implement some functions as well.
For example, I've seen that many pre-defined types implement MinValue and MaxValue, I would like my type T to implement these too. I've received some advice to just define an implicit function. But I wouldn't like that all the users were obliged to implement this function for these when it is already implemented. I could implement them at my code too, but it seems just to be a poor quick fix.
For example, when defining heaps, I would like to allowd users to construct a empty Heap. In these cases I want to inicialize value with the minimum value the type T could have. Obviously this code does not works.
class Heap[T](val value:T,val heaps:List[Heap[T]]){
def this()=this(T.MinValue,List())
}
I also would love to receive some advice about really go开发者_StackOverflow社区od online Scala 2.8 references.
A bunch of things, all loosely related by virtue of sharing a few methods (though with different return types). Sure sounds like ad-hoc polymorphism to me!
roll on the type class...
class HasMinMax[T] {
def maxValue: T
def minValue: T
}
implicit object IntHasMinMax extends HasMinMax[Int] {
def maxValue = Int.MaxValue
def minValue = Int.MinValue
}
implicit object DoubleHasMinMax extends HasMinMax[Double] {
def maxValue = Double.MaxValue
def minValue = Double.MinValue
}
// etc
class C[T : HasMinMax](param : T) {
val bounds = implicitly[HasMinMax[T]]
// now use bounds.minValue or bounds.minValue as required
}
UPDATE
The [T : HasMinMax]
notation is a context bound, and is syntactic sugar for:
class C[T](param : T)(implicit bounds: HasMinMax[T]) {
// now use bounds.minValue or bounds.minValue as required
}
You can either use type bounds:
trait Base
class C[T <: Base]
enabling C
to be parametrized with any type T
which is a subtype of Base
.
Or you can use implicit parameters to express requirements:
trait Requirement[T] {
def requiredFunctionExample(t: T): T
}
class C[T](implicit req: Requirement[T])
Thus, objects of class C
can only be constructed if there exists an implementation of the Requirement
trait for the type T
you wish to parametrize them with. You can place implementations of Requirement
for different types T
in, for instance, a package object, thus bringing them into scope whenever the corresponding package is imported.
精彩评论