我想要练习创造某种幺半群,即。常用类型的自定义包装类,允许我对它们进行基本操作:
abstract class WrappedVal[T](value: T) {
def +(that: WrappedVal[T]): WrappedVal[T]
def get: T = value
}
case class NumericValue(value: Double) extends WrappedVal[Double](value) {
override def +(that: WrappedVal[Double]): NumericValue = NumericValue(value + that.get)
}
case class StringValue(value: String) extends WrappedVal[String](value) {
override def +(that: WrappedVal[String]): StringValue = StringValue(value.substring(1) + that.get.substring(1))
}
通过这种方式,我可以做NumericValue(3)+NumericValue(4)
并获得NumericValue(7)
。
然后我想更多地包装这个值,所以我补充说:
case class Entry(bucket: Integer, value: WrappedVal[_])
现在我有一个函数,根据params返回Entry类型(它们总是具有相同的值类型,即NumericValue或StringValue或SomeOtherValue)和签名:
def readValue(vartype: String, value: String): WrappedVal[_] = {
if(vartype == "String") StringValue(value)
else NumericValue(value.toInt)
}
如此有效地得到:
val l = List(Entry(1,NumericValue(1)), Entry(1,NumericValue(2)), Entry(1,NumericValue(3)))
当我想使用我的自定义运算符时出现问题,例如在reduce子句中:
l.map(x => x.value).reduce(_+_)
这是因为scala可以在运行时找出类型(l.map(x => x.value)
属于List[WrappedVal[_]]
类型。
有关如何解决此问题的任何提示'正确的方式'?
答案 0 :(得分:0)
我正在玩你的代码,并让它工作
abstract class WrappedVal[T](value: T)(implicit A: ClassTag[T]) {
def +(that: WrappedVal[_]): WrappedVal[T] = {
classTag[T] match {
case t if t == classTag[String] => StringValueFunctions.add(this.asInstanceOf[WrappedVal[String]], that.asInstanceOf[WrappedVal[String]]).asInstanceOf[WrappedVal[T]]
case t if t == classTag[Double] => NumericValueFunctions.add(this.asInstanceOf[WrappedVal[Double]], that.asInstanceOf[WrappedVal[Double]]).asInstanceOf[WrappedVal[T]]
}
}
def get: T = value
}
case class NumericValue(value: Double) extends WrappedVal[Double](value)
case object NumericValueFunctions {
def add(value:WrappedVal[Double], that: WrappedVal[Double]): WrappedVal[Double] = NumericValue(value.get + that.get)
}
case class StringValue(value: String) extends WrappedVal[String](value)
case object StringValueFunctions{
def add(value: WrappedVal[String], that: WrappedVal[String]): WrappedVal[String] = StringValue(value.get.substring(1) + that.get.substring(1))
}
如果您希望此l.map(x => x.value).reduce(_+_)
能够工作
你需要一个def +(that: WrappedVal[_])
方法,这有点难看。
希望它能帮助您找到正确的方法'
答案 1 :(得分:0)
现在我有一个函数,取决于params返回Entry类型(它们总是具有相同的值类型,即NumericValue或StringValue或SomeOtherValue)
问题是编译器不知道这一点。您可以将readValue
来电分组来表达吗?即。
case class Entries[T](entries: List[Entry[T]]) {
def sum = entries.map(_.value).reduce(_ + _)
}
def readValues(...): Entries[_]
或者,如果您不想引入Entries
类型,则可以使用存在感:List[Entry[T]] forSome { type T }
。