2017-01-30 92 views
1

对于这两个代码块,我预计这两个块中的self引用都是Foo [A]。不过看起来第二个块不能编译。有人可以向我解释如何解决self参考?如何在这种情况下解决自引用?

trait Foo[A] { 
    def format(value:A):String 
    def bar[B](f:B=>A):Foo[B] = { 
    val self = this 
    new Foo[B] { 
     override def format(value: B): String = self.format(f(value)) 
    } 
    } 
} 

trait Foo[A] { 
    def format(value:A):String 
    val self = this 
    def bar[B](f:B=>A):Foo[B] = {  
    new Foo[B] { 
     override def format(value: B): String = self.format(f(value)) 
    } 
    } 
} 

回答

2

self得到分配this,这是一个特定实例的引用,你调用在调用一个方法(或构造函数)的人。

在第一片段中,调用Foo[A]类型的对象上的方法bar,这意味着在该点this意味着Foo[A]实例。在将this分配到self之后,您继续创建Foo的新实例,这次给出的类型参数为不同的类型,但是self

在第二个片段中,您说Foo[A]类型的对象有一个名为self的成员字段,并被分配到this。这将适用于Foo[_]的所有实例,无论您如何调用类型参数。当你创建一个第二Foo调用类型参数B,这第二个实例将仍然有一个成员字段self,其中被分配this,它在这一点上是Foo[B]色调self你声明的初始声明的一部分Foo

这意味着,在所述第二片段中,你的Foo[B]format方法实现访问本身的Foo[B]一个self参考,这会导致你所提到的类型的错误。

  • 的Foo [B]具有方法格式(值:B)
  • 方法bar需要一个函数,它接受一个B并将它转换为一个A
  • 您应用f: B => Avalue: B,把它变成一个A ,那么你试图喂AFoo[B]#format(value: B)

对不起,复杂的回应;简而言之:类型参数仅仅是实际类型的占位符名称,就像值参数是实际运行时值的占位符名称一样。将相同的推理应用于类型和值,推理它们会变得更容易。

+0

好的。我正在挠头。 'private [this] val self:Foo [A] = this',它编译得很好。 – pedrofurla

+0

非常感谢您花时间详细解释这一点。我知道了。对于其他没有得到它的人,我认为在抽象之前先用一些具体的时间替代A和B会有帮助。 – laiboonh