链式Scala性状中的super行为
为什么下面的链式Scala性状中的super行为,scala,traits,Scala,Traits,为什么下面的x.func返回“B扩展B扩展B”? 如何安排此代码以使其返回“B扩展A扩展基” 更新:一种安排如下。现在它在A和B中对func1有相同的定义。如果我尝试将其移动到派生的类中,它将不起作用。如何消除重复的func1 trait Base { def name = "Base" def func1(s: String) = s } trait Derived extends Base { def func = func1(name) } trait A extends
x.func
返回“B扩展B扩展B”
?
如何安排此代码以使其返回“B扩展A扩展基”
更新:一种安排如下。现在它在A
和B
中对func1
有相同的定义。如果我尝试将其移动到派生的
类中,它将不起作用。如何消除重复的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的哪个方法的方法:
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
(有关如何计算线性化的实际说明,请参阅)
编辑以回答评论:为什么名称总是返回“B”
?这是因为def name
方法被traitB
覆盖,返回“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
traitlegs
中的legs
与Dog
中的legs
不是一个单独的,这取决于您是在legs
还是Dog
中引用它。。。同样,如果对象是aB
,则您的def 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
,这样您就可以了解问题的核心,但另一方面,它并没有让我了解您可以做哪些更改以使其适合您。正如您所要求的,我已安排代码,以便它打印“B扩展A扩展基”
。我敢肯定还有很多其他的限制条件,但为什么它对您不起作用呢。这是问题的关键。为什么呢?感谢您提出的解决方案,但我确实希望每个trait的func定义相同。trait的超级调用在运行时解决。通过说trait A扩展了B
,你是在说A
只能混合到扩展B
的东西中。没有办法知道A
是否混入了一个直接扩展B
的类中,或者是在几个可堆叠的特征之后(…带A带B
)。因此,在特征声明的时候,不可能确定哪个特征将“超过”这个特定的修改,或者换句话说,超级调用将导致哪个修改。@huynhjl,请查看问题的更新。“现在,我正在努力摆脱func1的重复。”MushtaqAhmed,我看不出你在更新的问题中采纳了我更新的答案中的其他建议。因此,我不确定我是否还有其他好的想法,因为我没有足够的上下文和洞察力来理解您的约束。@huynhjl我无法在我的设计中指定一个私人成员,因此无法使用这种方法。但是你是对的,如果没有我正在努力抽象出来的很多上下文,可能就不可能在这个问题上工作。还有一些澄清:在真实场景中,名称是一个独立的方法,不能内联到func中。此外,我正在试验,看看func的定义是否在所有扩展基础的特征中都是相同的。
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