链式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
方法被trait
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
trait
legs
中的
legs
Dog
中的
legs
不是一个单独的,这取决于您是在
legs
还是
Dog
中引用它。。。同样,如果对象是a
B
,则您的
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