Reputation: 63
I have class Seq and I want to have method "multy" that adds number to List factors, but I want, that only Seq of Number types will have this method, for this example, val numbers should work with multy, and val strings shouldn't.
import scala.collection.mutable.ListBuffer
object Main extends App{
val strings = new Seq("f", "d", "a")
val numbers = new Seq(1,5,4,2)
val strings2 = new Seq("c", "b")
numbers.multy(5)
strings.multy(5)
val strings3 = strings2.concat(strings)
println(strings3)
println(numbers)
}
class Seq[T : Ordering] (initialElems: T*) {
override def toString: String = elems.toString
val factors = ListBuffer[Number](1)
val elems = initialElems.sorted
def concat(a:Seq[T]) = new Seq(a.elems ++ this.elems:_*)
def multy[T <: Number](a:Number) = {
factors += a;
}
}
Upvotes: 0
Views: 74
Reputation: 27595
If you want scala.Int
, scala.Long
, scala.Double
, etc to not be supported - because they don't extend Number
- you can define method as
def multy(a: Number)(implicit ev: T <:< Number): Unit = {
factors += a
}
However, considering that under the hood they could be extending Number
(if the compiler, decides that it should compile them as objects and not as primitives), usage of a type class would work better:
trait IsNumber[T] {
def asNumber(value: T): Number
}
object IsNumber {
implicit def numbersAreNumbers[T <: Number]: IsNumber[T] = t => t
implicit val intIsNumber: IsNumber[Int] = i => (i: Number)
... // the same for Long, Short, etc
}
which could be used in multy as evidence
def multy(a: Number)(implicit ev: IsNumber[T]): Unit = {
factors += a
}
and as normal type class in code that would need that knowledge for something:
def doSomethingWithElements(implicit isNumber: IsNumber[T]) = {
elems.map(isNumber.asNumber).toList // List[Number]
}
This would support both java.lang.*
Number
s as well as Scala's numbers definitions.
Upvotes: 1