Scala中的特征是接口还是抽象类?

时间:2017-09-11 14:02:59

标签: scala traits

我已经通过互联网阅读了Scala中的特征

  

可以提供具体成员的接口

这意味着,特征是界面,我们可以在界面中提供 body to methods 。我在这里有一个简单的查询,如果这可能比我的下面代码显示错误的原因:

  

错误:(6,8)对象Car继承冲突成员:方法   trait中的startEngine类型=>的车辆单元和方法startEngine   特性电机类型=>单位(注意:这可以解决   在对象Car中声明一个覆盖。)对象Car extends Vehical with   汽车{

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允许这样做。如果traits不是接口,那么我会将它们视为抽象类,这意味着scala中不允许使用接口。

另请告诉我如何解决这个歧义问题。如果多个特征中有相同的方法,我如何在子类中使用我的startEngine方法。

1 个答案:

答案 0 :(得分:5)

  

作为一名java开发人员,我不会在界面中提供body   但scala特征允许这个

Scala中的特征提供了定义默认实现的方法,Java starting version 8也是如此。在Scala中,它们主要用作mixins

关于编译错误,这是因为您使用Vehicle方法声明了MotorstartEngine这一事实,并且从编译器的角度产生了歧义。查看,因为您在两种实现中混合。要克服这个问题,您需要显式覆盖实现类/ trait中的方法:

override def startEngine: Unit = super.startEngine

需要注意的一点是,super这里指的是mixin链中提供startEngine方法的最后一个特征,在本例中为Motor。这意味着您将看到:

Motor Start
Stop Engine

我认为这不是你想要的。

可以做的是要求Vehicle使用self types混合Motor实施:

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