I am searching for a way to restrict my polymorphic class to types that have a certain member function.
class Table[T](bla: Array[T]) {
val symbols = bla
symbols.foreach( x => x * probability(x))
def probability(t: T) : Double = ...
}
This code does not compile because T doesnt have member *. How can I assure this. I dont want to use inheritance.
Edit: probability is actually implemented. It returns a Double.
Any ideas?
The problem can be solved in different ways. For example, if you just want type
Tto have some method (and you don’t care whether this method defined on the object or there is implicit conversion that coverts object to something that has this method), then you can use view bounds. Here is an example that expects typeTto have methoddef *(times: Int): T:Stringdoes not have method*, but there exist an implicit conversion to StringOps that has this method.Here is another example. In this case I restricting type
Twith methoddef size: Int:Listhas methodsize, and it also works as expected.But this could be more involving if you are working with numeric values like ints, floats, doubles, etc. In this case I can recommend you to use context bound. Scala has Numeric type class. You can use it to work with numbers without knowledge about their type (with
Numericyou can actually work with anything that can be represented as number, so your code would be much more general and abstract). Here is an example if it:Update
As you noted in comments,
Numericstill does not solve your problem, because it can only work on the numbers of the same type. You can simply solve this problem by introducing new type class. Here is an example of it:With
DoubleConverttype class andT : Numeric : DoubleConvertcontext bound you are not only saying, thatTshould be some kind of number, but also that there should exist some evidence, that it can be converted fromDouble. You are receiving such evidence withimplicitly[DoubleConvert[T]]and then you are using it to convertDoubletoT. I definedConvertfor Double -> Int and Double -> BigInt, but you can also define you own for the types you need.