scala - super 链式 Scala 特征的行为

标签 scala traits

为什么x.func以下返回 "B extends B extends B" ?
如何安排此代码以使其返回 "B extends A extends Base" ?

trait Base {
  def name = "Base"
  def func = name
}

trait A extends Base {
  override def name = "A"
  override def func = name + " extends " + super.func
}

trait B extends Base {
  override def name = "B"
  override def func = name + " extends " + super.func
}

val x = new Base with A with B
println(x.func)

更新:一种安排可能如下。它现在具有 func1 的相同定义在 AB .如果我尝试将其移至 Derived 则不起作用类(class)。任何想法如何删除 func1 的重复?
trait Base {
  def name = "Base"
  def func1(s: String) = s
}

trait Derived extends Base {
  def func = func1(name)
}

trait A extends Derived {
  override def func1(s: String) = s + " extends " + super.func1(super.name)
  override def name = "A"
}

trait B extends Derived {
  override def func1(s: String) = s + " extends " + super.func1(super.name)
  override def name = "B"
}

val x = new Base with A with B
println(x.func)

最佳答案

我认为继承令实际上可能是您正在寻求的继承令。如果您更换 " extends "一个显示调用哪个特征的方法:

trait Base {
  def name = "Base"
  def func = "Base." + name
}

trait A extends Base {
  override def name = "A"
  override def func = name + " A.extends " + super.func
}

trait B extends Base {
  override def name = "B"
  override def func = name + " B.extends " + super.func
}

val x = new Base with A with B
println(x.func)
// B B.extends B A.extends Base.B

只是name总是 "B" .换句话说:
trait Base { def func = "Base" } 
trait A extends Base { override def func = "A extends " + super.func }
trait B extends Base { override def func = "B extends " + super.func }
val x = new Base with A with B
println(x.func)
// B extends A extends Base

这就是你想要的......

您的示例的完全线性化是:
Object, B, A, Base, ScalaObject, AnyRef, Any

(见 http://ofps.oreilly.com/titles/9780596155957/ScalaObjectSystem.html#Linearization 关于如何计算线性化的实用解释)

编辑回答评论:为什么是 name总是返回 "B" ?那是因为 def name方法被特征 B 覆盖返回 "B" .这就是继承的全部意义,能够在父类(super class)中使用子类中细化的行为:
trait Legs { 
  def legs: Int 
  def printLegs() { println("I have " + legs + " legs") }
}

class Dog extends Legs { def legs = 4 }
class Chicken extends Legs { def legs = 2 }

new Dog printLegs
// I have 4 legs
new Chicken printLegs
// I have 2 legs
legs性状 Legslegs 不同在 Dog取决于您是否在 Legs 中引用它或 Dog ... 同样,您的 def name将始终返回 "B"如果您的对象是 B .

看起来您想使用 name 作为私有(private)方法:
trait Base { 
  private def _name() = "Base"
  def func = _name
} 
trait A extends Base { 
  private def _name() = "A"
  override def func = _name + " extends " + super.func
}
trait B extends Base { 
  private def _name() = "B"
  override def func = _name + " extends " + super.func
}
val x = new Base with A with B
println(x.func)
// B extends A extends Base

我发现如果没有明确的对象模型,使用 trait 和继承很快就会变得复杂。我假设您已清理/简化示例以使用通用名称,如 A, B, Base, func这样您就可以找到问题的核心,但另一方面,它并没有让我了解您可以做哪些更改以使其对您有用。正如你所问的,我已经安排了代码以便打印 "B extends A extends Base" .我敢肯定还有很多其他的限制不在问题中,为什么它对你不起作用。

关于scala - super 链式 Scala 特征的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7694600/

相关文章:

scala - 我应该什么时候使用包,什么时候在 Scala 中使用对象?

rust - 提供将 &self 转换为特征对象的方法

rust - 为什么 `ToString` 项的迭代器要求它们也为 `Display`?

json - 使用 Play 2.4 中其他属性的依赖关系验证 json 属性

c++ - traits 类是如何工作的,它们有什么作用?

php - 与其他 trait 方法的冲突

scala - 为什么子特征中需要 "abstract override"而不是单独的 "override"?

scala - 无法识别的选项 : -Xcext. enabled=true 错误 JVM、JRuby、Scala 和 RubyMine

javascript - 通过 playframework 将动态创建的数据传递给 d3

scala - 从 DataFrame 中选择列时 $ 符号如何工作?