【问题标题】:Is Traits in Scala an Interface or an Abstract Class?Scala 中的 Traits 是接口还是抽象类?
【发布时间】:2017-09-11 14:02:59
【问题描述】:

我在网上了解到 Scala 中的 Traits 是

可以提供具体成员的接口

这意味着,特征是接口,我们可以在接口中为方法提供主体。我在这里有一个简单的查询,如果这可能比我下面的代码显示错误的原因:

错误:(6, 8) 对象 Car 继承了冲突的成员:方法 startEngine 在 trait Vehical 类型 => 单元和方法 startEngine 在 trait Motor of type => Unit 中(注意:这可以通过 在对象 Car 中声明一个覆盖。)对象 Car 扩展了 Vehical 电机{

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

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

【问题讨论】:

  • here 有人问过类似的问题。但这里有一个快速的答案:实际上,特质两者兼而有之。 Traits 是mixins,但是如果你需要和 Java 做个比较的话,它们正好介于接口和抽象类之间。与接口的相似之处在于,一个特征可以混合到多个类中,并且它不能具有带参数的构造函数。与抽象类的相似之处在于它可以包含方法的实现。
  • 非常清晰,谢谢。你能告诉我是什么使创建特征。我的意思是当我们有接口和抽象类时为什么要使用 Traits。
  • 嘿,我现在才看到这条评论。 @Yuval 提供了一个很好的答案,我认为您上面的问题现在已被弃用:)

标签: scala traits


【解决方案1】:

作为一名 Java 开发人员,我不会在接口内提供正文 但是 scala 特性允许这样做

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

关于编译错误,这是因为您使用 startEngine 方法声明了 VehicleMotor,从编译器的角度来看,这会产生歧义,因为您是在两种实现中混合。为了克服这个问题,您需要在实现类/特征中显式覆盖该方法:

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

【讨论】:

  • 谢谢@Yuval Itzchakov :) 这正是我一直在寻找的,如果需要,如何调用所有超级方法。此外,我不想为我已经在 Traits 中实现的方法提供定义。
猜你喜欢
  • 2021-12-17
  • 1970-01-01
  • 2013-04-12
  • 1970-01-01
  • 2011-05-22
  • 2012-09-12
  • 2011-03-11
  • 2010-10-11
  • 1970-01-01
相关资源
最近更新 更多