是否可以从 self 类型调用重写的方法? [英] Is it possible to call an overridden method from self type?

查看:36
本文介绍了是否可以从 self 类型调用重写的方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑一下:

 class Foo { def foo = "foo" }trait Bar { self: Foo =>覆盖 def foo = "bar"}

我惊喜地发现这是可能的,并且按预期工作:

带有 Bar foo 的新 Foo

返回bar".问题是 Bar.foo 是否有可能调用 Foo.foo,就像在普通"继承情况下经常做的那样.override def foo = super.foo + "bar" 不起作用(说foo 不是 AnyRef 的成员),并且 override def foo = self.foo + "bar" (它最终只是调用自己,并导致无限递归).我尝试了一些其他组合(如 self.Foo.fooFoo.this.foo 等),但没有任何运气.

这是不可能的吗?

解决方案

没有.无法从 self 类型调用覆盖方法.

首先,特征 Bar 不是 Foo 类的继承者,所以不可能使用 super.foo.

其次也不可能使用 self.foo,因为 self 实际上是 Bar with Foo 类型.可以通过在typer后打印程序来显示:

$ scalac -Xprint:typer test.scala[[typer 末尾的语法树]]//test.scala包<空>{类 Foo 扩展了 scala.AnyRef {def (): Foo = {Foo.super.();()};def foo: String = "foo"};抽象 trait Bar extends scala.AnyRef { self: Bar with Foo =>def/*Bar*/$init$(): 单位 = {()};覆盖 def foo: String = "bar"};class FooBar 使用 Bar { 扩展 Foodef (): FooBar = {FooBar.super.();()}};对象 TestApp 扩展了 scala.AnyRef {def (): TestApp.type = {TestApp.super.();()};def main(args: Array[String]): Unit = {val a: FooBar = new FooBar();scala.this.Predef.println(a.foo)}}}

因此,使用 self.foo,您正在尝试访问特征 Bar 的方法 foo.此类行为符合 Scala 规范 (PDF):

<块引用>

模板语句的序列可以用一个正式的前缀参数定义和箭头,例如x =>,或 x:T =>.如果正式给定参数,它可以用作引用 this 的别名整个模板主体.如果形参来对于类型 T,此定义会影响对象的自身类型 S底层类或对象如下:令 C 为类的类型或特征或定义模板的对象.如果给定了类型 T形式自参数,S 是 T 和 C 的最大下界.如果没有给出了类型 T,S 就是 C.在模板内部,this 的类型是假设为 S.

可以使用反射访问该方法,但我认为这不是您要找的.

Consider this:

 class Foo { def foo = "foo" }
 trait Bar { self: Foo =>
    override def foo = "bar"
 }

I was pleasantly surprised to find out that this is possible, and works as expected:

new Foo with Bar foo 

returns "bar". The question is whether it is possible for Bar.foo to invoke Foo.foo, like one would often do in the "ordinary" inheritance case. override def foo = super.foo + "bar" does not work (says "foo is not a member of AnyRef), and neither does override def foo = self.foo + "bar" (it ends up just calling itself, and results in infinite recursion). I tried a few other combinations (like self.Foo.foo, Foo.this.foo etc.), but without any luck.

Is this just impossible?

解决方案

No. It is impossible to call overridden method from a self type.

Firstly the trait Bar is not a successor of class Foo so it is not possible using super.foo.

And secondly it is also not possible using self.foo since self is actually of type Bar with Foo. It can be shown by printing the program after 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)
    }
  }
}

So with self.foo you are trying to access the method foo of the trait Bar. Such behavior matches the 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.

It is possible to access the method using reflection but I think that it is not what you are looking for.

这篇关于是否可以从 self 类型调用重写的方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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