这是关于表示类型的两个 问题的后续,它们是一个 trait 的类型参数,旨在表示有界类型成员(或类似成员)的基础类型。我已经成功地创建了类的实例,例如ConcreteGarage
,具有cars
有界类型成员的实例CarType
。
trait Garage {
type CarType <: Car[CarType]
def cars: Seq[CarType]
def copy(cars: Seq[CarType]): Garage
def refuel(car: CarType, fuel: CarType#FuelType): Garage = copy(
cars.map {
case `car` => car.refuel(fuel)
case other => other
})
}
class ConcreteGarage[C <: Car[C]](val cars: Seq[C]) extends Garage {
type CarType = C
def copy(cars: Seq[C]) = new ConcreteGarage(cars)
}
trait Car[C <: Car[C]] {
type FuelType <: Fuel
def fuel: FuelType
def copy(fuel: C#FuelType): C
def refuel(fuel: C#FuelType): C = copy(fuel)
}
class Ferrari(val fuel: Benzin) extends Car[Ferrari] {
type FuelType = Benzin
def copy(fuel: Benzin) = new Ferrari(fuel)
}
class Mustang(val fuel: Benzin) extends Car[Mustang] {
type FuelType = Benzin
def copy(fuel: Benzin) = new Mustang(fuel)
}
trait Fuel
case class Benzin() extends Fuel
我可以轻松地创建 s 的实例,Car
例如Ferrari
s 和Mustang
s 并将它们放入 aConcreteGarage
中,只要它很简单:
val newFerrari = new Ferrari(Benzin())
val newMustang = new Mustang(Benzin())
val ferrariGarage = new ConcreteGarage(Seq(newFerrari))
val mustangGarage = new ConcreteGarage(Seq(newMustang))
但是,如果我只是根据标志返回一个或另一个,并尝试将结果放入车库,它会失败:
val likesFord = true
val new_car = if (likesFord) newFerrari else newMustang
val switchedGarage = new ConcreteGarage(Seq(new_car)) // Fails here
单独的开关工作正常,它是对ConcreteGarage
构造函数的调用失败并出现相当神秘的错误:
error: inferred type arguments [this.Car[_ >: this.Ferrari with this.Mustang <: this.Car[_ >: this.Ferrari with this.Mustang <: ScalaObject]{def fuel: this.Benzin; type FuelType<: this.Benzin}]{def fuel: this.Benzin; type FuelType<: this.Benzin}] do not conform to class ConcreteGarage's type parameter bounds [C <: this.Car[C]]
val switchedGarage = new ConcreteGarage(Seq(new_car)) // Fails here
^
我曾尝试将那些神奇的[C <: Car[C]]
表示类型参数放在任何地方,但没有成功找到神奇的地方。