这是previous question的后续版本,其中我有一个特征成员Garage
的特征CarType
,其本身有一个类型成员FuelType
,而我需要一个函数refuel
,它可以将CarType
的实例作为第一个参数,将第一个参数的FuelType
的实例作为第二个参数。
下面两个特征的答案是给Car
一个表示类型C <: Car[C]
。我现在遇到的问题是我无法弄清楚如何在实现Garage
的具体类上定义类型参数,例如ConcreteGarage
以下{/ 1}}。
trait Fuel
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
})
}
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 ConcreteGarage(val cars: Seq[ConcreteGarage#CarType]) extends Garage {
type CarType = Car[CarType] // Nope
//type CarType = Car[Any] // Nope
//type CarType = Car[Nothing] // Nope
//type CarType = Car[Car] // Nope
//type CarType <: Car[CarType] // Nope
def copy(cars: Seq[CarType]) = new ConcreteGarage(cars)
}
答案 0 :(得分:1)
这就是为什么我要提防在你的余生中携带另一个类型参数的丑陋:)
class ConcreteGarage[C <: Car[C]](val cars: Seq[C]) extends Garage {
type CarType = C
def copy(cars: Seq[C]) = new ConcreteGarage(cars)
}
当然,如果你有特定的车库,它会更简单。
case class Benzin(litres: Int) extends Fuel
case class Mustang(fuel: Benzin) extends Car[Mustang] {
type FuelType = Benzin
def copy(fuel: Benzin) = Mustang(fuel)
}
case class MustangGarage(cars: Seq[Mustang]) extends Garage {
type CarType = Mustang
def copy(cars: Seq[Mustang]) = MustangGarage(cars)
}
val m = Mustang(Benzin(0))
val g0 = MustangGarage(Seq(m))
val g1 = g0.refuel(m, Benzin(45))