super 在链式 Scala 特征中的行为 [英] Behaviour of super in chained Scala traits

查看:42
本文介绍了super 在链式 Scala 特征中的行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为什么下面的x.func会返回"B extends B extends B"?如何安排这段代码,使其返回"B extends A extends Base"?

Why does x.func below return "B extends B extends B"? How to arrange this code so that it returns "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)

更新:一种安排如下.它现在在 AB 中具有相同的 func1 定义.如果我尝试将其移动到 Derived 类,则它不起作用.任何想法如何删除 func1 的重复?

Update: One arrangement could be as follows. It now has identical definitions of func1 in A and B. It does not work if I try to move it to the Derived class. Any ideas how to remove the repetition of 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 " 替换为一个显示调用哪个特征的方法的代码:

I think the inheritance order may actually be the one your are seeking. If you replace the " extends " with one that shows which method of which trait is called:

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".换句话说:

It's just that name is always "B". In other words:

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

这就是你想要的...

您的示例的完整线性化是:

The full linearization of your example is:

Object, B, A, Base, ScalaObject, AnyRef, Any

(参见 http://ofps.oreilly.com/titles/9780596155957/ScalaObjectSystem.html#Linearization 有关如何计算线性化的实用说明)

(see http://ofps.oreilly.com/titles/9780596155957/ScalaObjectSystem.html#Linearization for a practical explanation on how to figure out the linearization)

编辑回答评论: 为什么 name 总是返回 "B"?这是因为 def name 方法被特征 B 覆盖以返回 "B".这就是继承的全部意义,能够在子类中细化的超类行为中使用:

Edit to answer comment: why is the name always returns "B"? That's because the def name method is overridden by the trait B to return "B". That's the whole point of inheritance, to be able to use in superclasses behavior that is refined in subclasses:

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 中的

legsDog 中的 legs 不是独立的,这取决于你是否参考它在 LegsDog... 同样,如果您的对象,您的 def name 将始终返回 "B"B.

legs in trait Legs is not a separate one than legs in Dog depending on if you refer to it in Legs or Dog... Similarly, your def name will always return "B" if your object is a B.

看起来您想使用 name 作为私有方法:

It looks like you want to use name as a private method:

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".我敢肯定,还有很多其他限制因素不在问题中,为什么它对您不起作用.

I find that if there isn't a clear object model, using trait and inheritance quickly gets complicated. I assume you sanitized/simplified the example to use generic names like A, B, Base, func so that you get to the core of the issue, but on the other hand it doesn't give me any insights on what changes you could do to make it work for you. As you asked I've arrange the code so that it prints "B extends A extends Base". I'm sure there are a bunch of other constraints that aren't in the question why it won't work for you.

这篇关于super 在链式 Scala 特征中的行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆