Scala 中的 Traits 是接口还是抽象 Class?
Is Traits in Scala an Interface or an Abstract Class?
我在网上了解到 Scala 中的 Traits 是
interfaces that can provide concrete members
这意味着,特征是接口,我们可以在接口中为方法提供主体。我在这里有一个简单的查询,如果可能的话,为什么我的下面的代码显示错误:
Error:(6, 8) object Car inherits conflicting members: method
startEngine in trait Vehical of type => Unit and method startEngine
in trait Motor of type => Unit (Note: this can be resolved by
declaring an override in object Car.) object Car extends Vehical with
Motor {
trait Vehical {
def startEngine : Unit = {
println("Vehical Start")
}
def stopEngine
}
trait Motor {
def startEngine : Unit = {
println("Motor Start")
}
def stopEngine
}
object Car extends Vehical with Motor {
override def stopEngine : Unit = {
println("Stop Engine")
}
def main(args: Array[String]): Unit = {
Car.startEngine
Car.stopEngine
}
}
作为一名 java 开发人员,我不会在接口内部提供 body,但 scala traits 允许这样做。如果特征不是接口,那么我会将它们视为抽象 class,这意味着 scala 中不允许使用接口。
另外请告诉我如何解决这个歧义问题。如果相同的方法在多个特征中可用,我如何在子 class 中使用我的 startEngine 方法。
Being a java developer I would have not provided body inside interface
but scala traits allowed this
Scala 中的特征提供了定义默认实现的方法,Java starting version 8. In Scala, they are primarily used as mixins。
关于编译错误,这是因为您使用 startEngine
方法同时声明了 Vehicle
和 Motor
,这造成了编译器的歧义观点,因为你混合了两种实现。为了克服这个问题,您需要在实现 class/trait:
中显式覆盖该方法
override def startEngine: Unit = super.startEngine
需要注意的一件重要事情是 super
这里指的是混合链中的最后一个特征,它提供了 startEngine
方法,在本例中是 Motor
。这意味着您会看到:
Motor Start
Stop Engine
我认为这不是你想要的。
可以做的是要求 Vehicle
在 Motor
实现中使用 self types:
进行混合
trait Vehicle {
self: Motor =>
def startEngine: Unit = {
println("Vehicle Start")
startMotor
}
def stopEngine: Unit = {
println("Stopping Engine")
stopMotor
}
}
并仅根据电机定义您的 Motor
方法:
trait Motor {
def startMotor: Unit = {
println("Motor Start")
}
def stopMotor: Unit = {
println("Stop Motor")
}
}
然后你把所有东西都混进去:
object Car extends Vehicle with Motor
并调用:
def main(args: Array[String]): Unit = {
Car.startEngine
Car.stopEngine
}
你得到:
Vehicle Start
Motor Start
Stopping Engine
Stop Motor
我在网上了解到 Scala 中的 Traits 是
interfaces that can provide concrete members
这意味着,特征是接口,我们可以在接口中为方法提供主体。我在这里有一个简单的查询,如果可能的话,为什么我的下面的代码显示错误:
Error:(6, 8) object Car inherits conflicting members: method startEngine in trait Vehical of type => Unit and method startEngine in trait Motor of type => Unit (Note: this can be resolved by declaring an override in object Car.) object Car extends Vehical with Motor {
trait Vehical {
def startEngine : Unit = {
println("Vehical Start")
}
def stopEngine
}
trait Motor {
def startEngine : Unit = {
println("Motor Start")
}
def stopEngine
}
object Car extends Vehical with Motor {
override def stopEngine : Unit = {
println("Stop Engine")
}
def main(args: Array[String]): Unit = {
Car.startEngine
Car.stopEngine
}
}
作为一名 java 开发人员,我不会在接口内部提供 body,但 scala traits 允许这样做。如果特征不是接口,那么我会将它们视为抽象 class,这意味着 scala 中不允许使用接口。
另外请告诉我如何解决这个歧义问题。如果相同的方法在多个特征中可用,我如何在子 class 中使用我的 startEngine 方法。
Being a java developer I would have not provided body inside interface but scala traits allowed this
Scala 中的特征提供了定义默认实现的方法,Java starting version 8. In Scala, they are primarily used as mixins。
关于编译错误,这是因为您使用 startEngine
方法同时声明了 Vehicle
和 Motor
,这造成了编译器的歧义观点,因为你混合了两种实现。为了克服这个问题,您需要在实现 class/trait:
override def startEngine: Unit = super.startEngine
需要注意的一件重要事情是 super
这里指的是混合链中的最后一个特征,它提供了 startEngine
方法,在本例中是 Motor
。这意味着您会看到:
Motor Start
Stop Engine
我认为这不是你想要的。
可以做的是要求 Vehicle
在 Motor
实现中使用 self types:
trait Vehicle {
self: Motor =>
def startEngine: Unit = {
println("Vehicle Start")
startMotor
}
def stopEngine: Unit = {
println("Stopping Engine")
stopMotor
}
}
并仅根据电机定义您的 Motor
方法:
trait Motor {
def startMotor: Unit = {
println("Motor Start")
}
def stopMotor: Unit = {
println("Stop Motor")
}
}
然后你把所有东西都混进去:
object Car extends Vehicle with Motor
并调用:
def main(args: Array[String]): Unit = {
Car.startEngine
Car.stopEngine
}
你得到:
Vehicle Start
Motor Start
Stopping Engine
Stop Motor