为什么以下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
类,它就不起作用。任何想法如何删除重复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)
答案 0 :(得分:10)
我认为继承令可能实际上是你正在寻求的。如果将" 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"
。这是继承的全部要点,能够在子类中精炼的超类行为中使用:
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
中的{p> Legs
与legs
中的Dog
不是一个独立的,具体取决于您是否在Legs
或{{1}中引用它}同样,如果您的对象是Dog
,则def name
将始终返回"B"
。
看起来你想使用name作为私有方法:
B
我发现如果没有清晰的对象模型,使用特征和继承会很快变得复杂。我假设您清理/简化了示例以使用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
这样的通用名称,以便您了解问题的核心,但另一方面,它并没有给我任何有关您可以做什么更改的见解它适合你。正如您所说,我已经安排了代码,以便打印A, B, Base, func
。我确信还有一些其他约束不在为什么它对你不起作用。