考虑一下:
class Foo { def foo = "foo" }
trait Bar { self: Foo =>
override def foo = "bar"
}
我惊喜地发现这是可能的,并且按预期工作:
new Foo with Bar foo
返回“酒吧”。问题是
Bar.foo
是否可行调用 Foo.foo
,就像在“普通”继承案例中经常做的那样。 override def foo = super.foo + "bar"
不起作用(说“foo 不是 AnyRef 的成员),override def foo = self.foo + "bar"
也不起作用(它最终只是调用自己,并导致无限递归)。我尝试了其他一些组合(如
self.Foo.foo
、 Foo.this.foo
等),但没有任何运气。这是不可能的吗?
最佳答案
不。不可能从 self 类型调用重写的方法。
首先是特质Bar
不是类 Foo
的继承者所以不可能使用 super.foo
.
其次,也不能使用 self.foo
自 self
实际上是类型 Bar with Foo
.可以通过在typer
后面打印程序来显示:
$ scalac -Xprint:typer test.scala
[[syntax trees at end of typer]] // test.scala
package <empty> {
class Foo extends scala.AnyRef {
def <init>(): Foo = {
Foo.super.<init>();
()
};
def foo: String = "foo"
};
abstract trait Bar extends scala.AnyRef { self: Bar with Foo =>
def /*Bar*/$init$(): Unit = {
()
};
override def foo: String = "bar"
};
class FooBar extends Foo with Bar {
def <init>(): FooBar = {
FooBar.super.<init>();
()
}
};
object TestApp extends scala.AnyRef {
def <init>(): TestApp.type = {
TestApp.super.<init>();
()
};
def main(args: Array[String]): Unit = {
val a: FooBar = new FooBar();
scala.this.Predef.println(a.foo)
}
}
}
所以与
self.foo
您正在尝试访问该方法 foo
性状 Bar
.此类行为符合 Scala Specification (PDF):The sequence of template statements may be prefixed with a formal parameter definition and an arrow, e.g. x =>, or x: T =>. If a formal parameter is given, it can be used as an alias for the reference this throughout the body of the template. If the formal parameter comes with a type T, this definition affects the self type S of the underlying class or object as follows: Let C be the type of the class or trait or object defining the template. If a type T is given for the formal self parameter, S is the greatest lower bound of T and C. If no type T is given, S is just C. Inside the template, the type of this is assumed to be S.
可以使用反射访问该方法,但我认为这不是您想要的。
关于scala - 是否可以从 self 类型调用重写的方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36945333/