为什么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
的相同定义在 A
和 B
.如果我尝试将其移至 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
性状 Legs
与 legs
不同在 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/