Reputation: 1125
Lets I have a utility class called MathUtil.
and it looks like this .
abstract class MathUtil(T:Numeric){
def nextNumber(value:T)
def result():T
}
Lets I subclass it this way
class SumUtil[T:Numeric] extends MathUtil[T]{
private var sum:T = 0
override def nextNumber(value:T){
sum = sum + value
}
override def result():T = sum
}
I have a problem with the statement
private var sum:T = 0
Now , I have to initialize to sum to 0. I would guess any numeric to have a way to represent 0. Im pretty new to scala. How do I solve this issue ?
Upvotes: 7
Views: 1345
Reputation: 379
I think that there needs to be a little clarification of exactly what you're trying to accomplish. From the Scala docs, the Numeric type itself is generic. My feeling here is what you actually want is to describe a MathUtil abstraction that handles any Numeric[T] rather than subclasses of Numeric[_] which is what your code is currently describing. Here is the correct implementation based on that assumption.
//Define a MathUtil that works on any T
abstract class MathUtil[T] {
def nextNumber(value: T)
def result(): T
}
//Define a SumUtil that works on any T that has an available Numeric
//Will search implicit scope, but also allows you to provide an
//implementation if desired.
class SumUtil[T](implicit n: Numeric[T]) extends MathUtil[T] {
//Use the Numeric to generate the zero correctly.
private var sum: T = n.zero
//Use the Numeric to correctly add the sum and value
override def nextNumber(value: T) = sum = n.plus(sum, value)
override def result(): T = sum
}
//Test that it works.
val a = new SumUtil[Int]
val b = List(1,2,3)
b map a.nextNumber //Quick and dirty test... returns a meaningless list
println(a.result) //Does indeed print 6
If the above doesn't do what you want, please clarify your question.
Upvotes: 0
Reputation: 139048
The Numeric
type class instance has a zero
method that does what you want:
class SumUtil[T: Numeric] extends MathUtil[T] {
private var sum: T = implicitly[Numeric[T]].zero
override def nextNumber(value: T) {
sum = implicitly[Numeric[T]].plus(sum, value)
}
override def result(): T = sum
}
Note that you also need the instance for the plus
method, unless you import Numeric.Implicits._
, in which case you can use +
. You can also clean the code up a bit by not using the context bound syntax in this case:
class SumUtil[T](implicit ev: Numeric[T]) extends MathUtil[T] {
import Numeric.Implicits._
private var sum: T = ev.zero
override def nextNumber(value: T) {
sum = sum + value
}
override def result(): T = sum
}
This is exactly equivalent: the context bound version is just syntactic sugar for this implicit argument, but if you need to use that argument explicitly (as you do here, for its zero
), I find it cleaner to write the desugared version.
Upvotes: 12