如何创建包含数字数据类型的协变数据结构?
在scala中,我可以创建一个协变数据结构,其中包含类型参数的层次结构:
abstract class Car[+T] {
def value: T
}
class RaceCar extends Car[RacingWheel] {
def value: RacingWheel = new RacingWheel
}
class NormalCar extends Car[BoringWheel] {
def value: BoringWheel = new BoringWheel
}
class Wheel
case class RacingWheel() extends Wheel
case class BoringWheel() extends Wheel
object Car {
def main(args: Array[String]): Unit = {
val rCar: Car[Wheel] = new RaceCar
val nCar: Car[Wheel] = new NormalCar
val listCars: List[Car[Wheel]] = List(rCar, nCar)
}
}
但是,当我用数字数据类型替换Wheel时,我遇到了问题,因为数字数据类型没有AnyVal以外的公共类型父类:
abstract class Item[+N] {
def value: N
}
class IntItem(x : Int) extends Item[Int] {
override def value: Int = x
}
class DoubleItem(x : Double) extends Item[Double] {
override def value: Double = x
}
object Item {
def main(args: Array[String]): Unit = {
// ERROR Expression of IntItem does not conform to expected type Item[Number]
val iItem: Item[Number] = new IntItem(10)
// ERROR Expression of DoubleItem does not conform to expected type Item[Number]
val dItem: Item[Number] = new DoubleItem(10.9)
val l: List[Item[Number]] = List(iItem, dItem)
// ERROR: Expression of IntItem does not conform to expected type Item[Double]
val iItem2: Item[Double] = new IntItem(10)
val dItem2: Item[Double] = new DoubleItem(10.9)
val l2: List[Item[Double]] = List(iItem2, dItem2)
}
}
在协变数据结构之外,我得到了混合结果:
object NumberMain {
val a : Int = 5
val b : Double = 10.0
val list : List[Number] = List(a, b)
// works, so Number must be related to Int and Double, right?
val x : Number = 5
// ERROR: Expression of type Number doesn't conform to expected type Int
val y : Int = x
// does not work, so Number is not related to Int and Double after all...
}
我必须对Item数据结构进行哪些更改?我可以告诉它所有项目都可以看作是数字类型吗?
答案 0 :(得分:1)
在Scala中,sortFile()
和Int
不与共同的Double
类共享层次结构。在这些情况下,Typeclass pattern可以帮助您为没有常见超类型的类型定义额外的功能。
Number
trait MyNumber[A]
implicit case object IntMyNumber extends MyNumber[Int]
implicit case object DoubleMyNumber extends MyNumber[Double]
class Item[N](x: N)(implicit n: MyNumber[N]) {
def value: N = x
}
类构造函数现在需要使用Item
关键字标记的第二组参数。如果在没有这组参数的情况下调用方法,编译器会尝试从变量或导入中找到它(implicit
的实例),并且标记为MyNumber
(Where does Scala look for implicits?)。
我们在此定义implicit
和Int
实现Double
,但它没有做任何事情。我们可以把这个类写成:
MyNumber
它按预期工作:
class Item[N : MyNumber](x: N) {
def value: N = x
}
如果我们尝试在没有val iItem = new Item(1)
val dItem = new Item(1.0)
scala> iItem.value
res1: Int = 1
scala> dItem.value
res2: Double = 1.0
实例的情况下构建任何项目,则编译器会抛出错误:
MyNumber
如果您希望val sItem = new Item("S")
error: could not find implicit value for evidence parameter of type MyNumber[String]
成为任何数字,Scala会实现MyNumber
类型类。
修改强>
如果要为类型类添加一些针对每个数字不同的功能,可以执行以下操作:
Numeric