【发布时间】:2021-02-07 12:28:39
【问题描述】:
我有以下代码:
trait Vehicle {
def regNumber: String
def lotSize: Int
}
case class Car(regNumber: String) extends Vehicle {override val lotSize = 2}
case class Motorcycle(regNumber: String) extends Vehicle {override val lotSize = 1}
trait AbstractLot[+T <: Vehicle] {
def vehicle: T
def lotSize: Int = vehicle.lotSize
}
final case class CarLot(vehicle: Car) extends AbstractLot[Car]
final case class MotorcycleLot(vehicle: Motorcycle) extends AbstractLot[Motorcycle]
我想要一个ParkingLot 类型,它是一个抽象批次选项的数组。但是,当我写下面的代码时,Scala 编译器并不高兴
object ParkingLot {
type ParkingLot = Array[Option[AbstractLot[_]]]
//Case 1: OK
def mixMotorcycleCar(motorcycleCapacity: Int, carCapacity: Int): ParkingLot =
Array.fill[Option[MotorcycleLot]](motorcycleCapacity)(None) +: Array.fill[Option[CarLot]](carCapacity)(None)
//Case 2: Not OK
//T is a subclass of AbstractLot. Why isn't this working?
def homogenous[T <: AbstractLot[_]](capacity: Int): ParkingLot = Array.fill[Option[T]](capacity)(None)
//Case 3: Not OK
def carOnly(capacity: Int): ParkingLot = Array.fill[Option[CarLot]](capacity)(None)
}
我做错了什么?我应该如何修复我的代码,以便我可以拥有适用于案例 2 和案例 3 的 ParkingLot 类型?
【问题讨论】:
-
如果您不知道它是摩托车锁还是车辆锁,您希望如何使用每个批次?您需要重新设计它,使用 ADT (我会推荐这个) 或类型成员而不是类型参数。
-
感谢您的回复。我相信设计会更好。但是,我不确定我是否遵循您的解释。在案例 1 中,可以有一个由 AbstractLot 引用的 MotorLot 和 CarLot 的混合数组。但是为什么我不能像案例 2 和案例 3 那样拥有一个由 AbstractLot 引用的数组 CarLot(仅)?
-
正如@Ava 解释的由于不变性,这反过来又是由于可变性。这两个是为什么你不应该在 Scala 中使用普通的 Arrays 的原因,除非你真的需要它们来提高性能。我建议使用 List 或 Vector 或 ArraySeq 并确保您的解决方案是不可变的,使用
map之类的东西来创建修改后的副本. -
感谢您的回答和建议。这对我的理解很有帮助!