Предпосылка:
Я хочу отделить информацию, необходимую для создания экземпляра класса, от информации, необходимой для "запуска" класса. Однако информация, необходимая для «запуска» класса, может отличаться от класса к классу. Таким образом, я представляю, что у класса «есть» конкретная информация для его запуска, и оба они идут вместе.
Вот пример моего кода:
trait Machine {
type Params <: BaseParams
def start(machineParams: Params): Unit
}
trait BaseParams {
def speed: Int
def power: Int
}
class FlyingMachine() extends Machine {
type Params = FlyingParams
override def start(machineParams: Params): Unit = {
println(s"I'm flying with $machineParams")
}
}
trait FlyingParams extends BaseParams {
def height: Int
}
abstract class MachineOwner{
val machine: Machine
def params: machine.Params
def startMachine(): Unit = {
machine.start(params)
}
}
Это компилирует, проходит тесты, я счастлив.
Проблема: я использую val machine: Machine
для определения def params: machine.Params
. Мне сказали сделать это def
, чтобы дать разработчику больше свободы. Если я это сделаю, я больше не могу ссылаться на machine.Params
На данный момент я не знаю, как продолжить. Я продолжаю думать, что если это будет def
и определенно не val
, то моя архитектура неверна.
So
- Является ли мой подход к этой проблеме неправильным, учитывая предпосылку, с которой я изложил?
- Если это не так, есть ли способ достичь этого, используя
def
вместо val
в классе MachineOwner
?
EDIT
Учитывая ответ Алексея Романова, последний бит кода будет выглядеть так
abstract class MachineOwner{
type Params1 <: BaseParams
def machine: Machine { type Params = Params1 }
def params: Params1
def startMachine(): Unit = {
machine.start(params)
}
}
class FlyingMachineOwner(
machine: FlyingMachine
) extends MachineOwner {
override type Params1 = FlyingParams
override def params = FlyingParams(1,1,1)
}
Но это не компилируется, потому что ожидает переопределение специально для def machine: Machine { type Params = Params1 }
. Как это определить?