参数化比例特征
Parametrising Scala trait
免责声明:这个问题不是关于我是否应该这样做或它是否是一个好的设计,也不是任何相关的推理。问题是我该怎么做。我稍后解释为什么只是为了澄清。
我可以参数化 Scala 特征吗?我知道他们不能有构造函数参数 - 有不同的方法吗?对于类似的东西(当然这只是一个例子)
case class MyMachine(myDouble: Double) {
def methodEveryMachineHas(): Double = 2 * myDouble
}
trait Drivable {
this: MyMachine =>
def drive(x: Double): Double = HowToDriveFunction(x) * myDouble
}
object HowToDriveFunction extends (Double => Double) {
def apply(x:Double): Double = x + 6.0
}
val myMachine1 = new MyMachine(3.0)
myMachine1.methodEveryMachineHas // 6.0
myMachine1.drive(4.0) // error
val myMachine2 = new MyMachine(3.0) with Drivable
myClass1.methodEveryMachineHas // 6.0
myClass1.drive(4.0) // 30.0 = (4.0 + 6.0) * 3.0
如何将 HowToDriveFunction
传递给 drive
?
为什么我想要这个
将逻辑上不同的事物表示为程序上的不同事物,使代码有意义
函数应该固定锚定在对象(=实例化class)本身。因此,我希望它在创作过程中被赋予。然而,并非所有 MyMachine
都应该具有驱动能力。
想象MyMachine
是一台机器,Drivable
说它是可驱动的——如果某物不能按逻辑驱动,我认为它在技术上也不应该能够驱动,因此特征。但我仍然需要解释(通过 HowToDriveFunction
)这台特定机器(可能是汽车或飞机)的驱动是如何工作的。但是,我为什么要能够解释每台机器是如何驱动的呢?这是没有意义的。我只想向那些会开车的人解释。因此,我想将 HowToDriveFunction
赋予特征(表示机器可以驱动,因此首先应该能够驱动)。 如何驾驶工作不是能力(=特质),而是对机制的描述,我认为应该用功能来表示。如果它在逻辑上是不同的,那么如果用不同的编程结构来表示就更好了。
当然,我实际的东西与机器等无关 - 这只是一个例子。
如果我的功能是通过另一个特征给出的,我可以写
trait HowToDriveFunction {
this: Drivable =>
???
}
确保只有 Drivable
的人才能得到 HowToDriveFunction
的子 class,但这对我来说并不那么漂亮,原因已解释。
正在关注 "composition over inheritance"
最后但并非最不重要的一点是,我认为拥有 composition over inheritance 是件好事,因为我觉得它更容易推理代码。
我不确定我是否完全理解这个问题,但它似乎可以归结为
How do I pass HowToDriveFunction
to drive
?
并且能够定义 MyMachine
而无需驱动。
为此,您只需在 Drivable
中定义一个抽象成员。
case class MyMachine(myDouble: Double) {
def methodEveryMachineHas: Double = 2 * myDouble
}
trait Drivable {
this: MyMachine =>
protected def driveFunction: Double => Double
def drive(x: Double): Double = driveFunction(x) * myDouble
}
object HowToDriveFunction extends (Double => Double) {
def apply(x: Double): Double = x + 6.0
}
val myMachine1 = new MyMachine(3.0)
myMachine1.methodEveryMachineHas // 6.0
myMachine1.drive(4.0) // error
val myMachine2 = new MyMachine(3.0) with Drivable {
val driveFunction = HowToDriveFunction
}
myMachine2.methodEveryMachineHas // 6.0
myMachine2.drive(4.0) // 30.0 = (4.0 + 6.0) * 3.0
免责声明:这个问题不是关于我是否应该这样做或它是否是一个好的设计,也不是任何相关的推理。问题是我该怎么做。我稍后解释为什么只是为了澄清。
我可以参数化 Scala 特征吗?我知道他们不能有构造函数参数 - 有不同的方法吗?对于类似的东西(当然这只是一个例子)
case class MyMachine(myDouble: Double) {
def methodEveryMachineHas(): Double = 2 * myDouble
}
trait Drivable {
this: MyMachine =>
def drive(x: Double): Double = HowToDriveFunction(x) * myDouble
}
object HowToDriveFunction extends (Double => Double) {
def apply(x:Double): Double = x + 6.0
}
val myMachine1 = new MyMachine(3.0)
myMachine1.methodEveryMachineHas // 6.0
myMachine1.drive(4.0) // error
val myMachine2 = new MyMachine(3.0) with Drivable
myClass1.methodEveryMachineHas // 6.0
myClass1.drive(4.0) // 30.0 = (4.0 + 6.0) * 3.0
如何将 HowToDriveFunction
传递给 drive
?
为什么我想要这个
将逻辑上不同的事物表示为程序上的不同事物,使代码有意义
函数应该固定锚定在对象(=实例化class)本身。因此,我希望它在创作过程中被赋予。然而,并非所有 MyMachine
都应该具有驱动能力。
想象MyMachine
是一台机器,Drivable
说它是可驱动的——如果某物不能按逻辑驱动,我认为它在技术上也不应该能够驱动,因此特征。但我仍然需要解释(通过 HowToDriveFunction
)这台特定机器(可能是汽车或飞机)的驱动是如何工作的。但是,我为什么要能够解释每台机器是如何驱动的呢?这是没有意义的。我只想向那些会开车的人解释。因此,我想将 HowToDriveFunction
赋予特征(表示机器可以驱动,因此首先应该能够驱动)。 如何驾驶工作不是能力(=特质),而是对机制的描述,我认为应该用功能来表示。如果它在逻辑上是不同的,那么如果用不同的编程结构来表示就更好了。
当然,我实际的东西与机器等无关 - 这只是一个例子。
如果我的功能是通过另一个特征给出的,我可以写
trait HowToDriveFunction {
this: Drivable =>
???
}
确保只有 Drivable
的人才能得到 HowToDriveFunction
的子 class,但这对我来说并不那么漂亮,原因已解释。
正在关注 "composition over inheritance"
最后但并非最不重要的一点是,我认为拥有 composition over inheritance 是件好事,因为我觉得它更容易推理代码。
我不确定我是否完全理解这个问题,但它似乎可以归结为
How do I pass
HowToDriveFunction
todrive
?
并且能够定义 MyMachine
而无需驱动。
为此,您只需在 Drivable
中定义一个抽象成员。
case class MyMachine(myDouble: Double) {
def methodEveryMachineHas: Double = 2 * myDouble
}
trait Drivable {
this: MyMachine =>
protected def driveFunction: Double => Double
def drive(x: Double): Double = driveFunction(x) * myDouble
}
object HowToDriveFunction extends (Double => Double) {
def apply(x: Double): Double = x + 6.0
}
val myMachine1 = new MyMachine(3.0)
myMachine1.methodEveryMachineHas // 6.0
myMachine1.drive(4.0) // error
val myMachine2 = new MyMachine(3.0) with Drivable {
val driveFunction = HowToDriveFunction
}
myMachine2.methodEveryMachineHas // 6.0
myMachine2.drive(4.0) // 30.0 = (4.0 + 6.0) * 3.0