我正在尝试编译以下Scala代码:
// Something that Scala is very bad at: don't try and figure out if every type I *could* possibly use supports it,
// just let me use it until I try a type that doesn't. Or at least have AnyValue provide an abstraction for all
// Numeric Types (Interface)
trait NumericValue[T] {
def +(rhs : T, lhs : T) : T
}
implicit object ByteNumericValue extends NumericValue[Byte] {
def +(rhs : Byte, lhs : Byte) : Byte = (rhs + lhs).toByte
}
implicit object ShortNumericValue extends NumericValue[Short] {
def +(rhs : Short, lhs : Short) : Short = (rhs + lhs).toShort
}
implicit object IntNumericValue extends NumericValue[Int] {
def +(rhs : Int, lhs : Int) : Int = rhs + lhs
}
implicit object LongNumericValue extends NumericValue[Long] {
def +(rhs : Long, lhs : Long) : Long = rhs + lhs
}
implicit object BigIntNumericValue extends NumericValue[BigInt] {
def +(rhs : BigInt, lhs : BigInt) : BigInt = rhs + lhs
}
def doMath[T <: AnyVal](initializer : Long)(implicit Num : NumericValue[T]) : T = {
Num.+(initializer.asInstanceOf[T], initializer.asInstanceOf[T])
}
lazy val math = doMath[Short](0)
这里的想法是我需要一种方法使doMath对任何Integer进行操作,因此需要一个带有加法运算符的类型。我希望它与BigInt这样的大量数字或像Byte这样的非常小的数字不可知。
当我尝试编译时,我收到一个错误:
error: could not find implicit value for parameter Num: NumericValue[Short]
lazy val math = doMath[Short](0)
有什么想法吗?
答案 0 :(得分:0)
雷克斯是对的。由于x:Long表示x.asInstanceOf [Short]无效,因此当T为short时尝试将初始化程序转换为T时,例程失败。是的,这似乎是合法的。谢谢雷克斯!希望你回答而不是评论,所以我可以给你一个+1。
我确实对初始化程序的类型有一些控制权并且所有Byte都是它的逻辑类型但我需要考虑一下以确保这是唯一的问题,因为doMath的实际实现使用参数来获取延迟值类型,带有一组控制输出的选项。但上面是最简单的形式,我认为你的头上钉了一针。谢谢Rex Kerr!
答案 1 :(得分:0)
隐含的对象并不好。
尝试使用案例类
E.G:
case class LongNumericValue(l: Long) extends NumericValue[Long] {
def +(l2 : Long) : Long = l + l2
}
def doMath[T <: AnyVal](implicit Num : NumericValue[T]) : T = {
Num + Num
}
我会解释: 在上面的示例中,doMath采用NumericValue [T]类型的单个值(即NumericValue [Long]),但如果接收的值是Long类型,则编译器将查找它的隐式值,即case类。
注意我没有我的计算机,所以我无法测试这个,但过去我尝试以这种方式初始化变量时就是这样。