考虑一下:
class Foo { def foo = "foo" }
trait Bar { self: Foo =>
override def foo = "bar"
}
我惊喜地发现这是可能的,并按预期工作:
new Foo with Bar foo
返回" bar"。问题是Bar.foo
是否有可能调用Foo.foo
,就像人们经常在"普通"}中那样。继承案。 override def foo = super.foo + "bar"
不起作用(说" foo不是AnyRef的成员),override def foo = self.foo + "bar"
也没有(它最终只调用自身,导致无限递归)。
我尝试了一些其他组合(例如self.Foo.foo
,Foo.this.foo
等),但没有任何运气。
这是不可能的吗?
答案 0 :(得分:3)
没有。从自我类型调用重写方法是不可能的。
首先,特质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)匹配:
模板语句的序列可以以形式为前缀 参数定义和箭头,例如x =&gt;或x:T =&gt;。如果是正式的 给出参数,它可以作为参考的别名 整个模板的主体。如果形式参数来了 对于类型T,此定义会影响自我类型S. 底层类或对象如下:设C为类的类型 或定义模板的特征或对象。如果给出了类型T 形式自我参数,S是T和C的最大下界。如果不是 给出类型T,S只是C.在模板内部,它的类型是 假设是S.
可以使用反射访问该方法,但我认为它不是您正在寻找的。 p>
答案 1 :(得分:0)
我不知道任何特定的语法来解开基类和混合特征。 但是,通过区分重写方法和基类中的默认实现,可以轻松地手动实现结果:
class Foo { def foo = defaultFoo; def defaultFoo = "foo" }
trait Bar { self: Foo => override def foo = self.defaultFoo + "bar" }
正如预期的那样
new Foo with Bar foo == "foobar"
new Foo foo == "foo"
答案 2 :(得分:0)
你使你的特质扩展Foo
而不是使用自我类型:
class Foo {def foo = "foo"}
trait Bar extends Foo {
override def foo = super.foo + "bar"
}
new Foo with Bar foo // barfoo
另见this answer。