2017-01-30 51 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