2017-01-30 18 views
1

2ブロックのコードでは、両方のブロックのself参照がFoo [A]であると予想されました。しかし、2番目のブロックがコンパイルされないようです。誰かが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を割り当てられます。最初のスニペットで

は、その時点でthisFoo[A]のインスタンスを指すことを意味し、タイプFoo[A]のオブジェクトのメソッドbarを呼び出します。 thisselfに割り当てた後、Fooの新しいインスタンスを作成します。今回は、タイプパラメータに異なるタイプを指定しますが、selfです。

Foo[A]のオブジェクトにselfという名前のメンバーフィールドがあり、thisが割り当てられているとします。これは、typeパラメータの呼び出し方法に関係なく、Foo[_]のすべてのインスタンスに適用されます。あなたは、typeパラメータB呼び出す二Fooを作成すると、この2番目のインスタンスが、それにもかかわらず、この時点で、あなたが最初の宣言の一部として宣言Foo[B]色合いselfである、thisが割り当てられますメンバーフィールドselfを、持っていますFoo

これにより、第2のスニペットに、Foo[B]のあなたformatメソッドの実装を使用すると、上述のタイプのエラーが発生Foo[B]自体のself基準へのアクセスを有することを意味します。 (:B値)Bを取り、Aにそれを回す、あなたがvalue: Bf: B => Aを適用A

  • に変換する機能を取るbar
  • 方法

    • はFoo [B]はメソッドフォーマットを有しますあなたはフィードをしようとしますAFoo[B]#format(value: B)

    渦巻く応答のために申し訳ありません。要するに、型パラメータは、値パラメータが実際の実行時値のプレースホルダ名と同じように、実際の型の単なるプレースホルダ名です。タイプと値の両方に同じ推論を適用し、それらについての推論がより簡単になります。

  • +0

    良いキャッチです。私は頭を傷つけていた。 'private [this] val self:Foo [A] = this'これはうまくコンパイルされます。 – pedrofurla

    +0

    これを徹底的に説明する時間をとってくれてありがとう。わかった。それを得られない人たちのために、抽象化の前にまずAとBを具体的な時間に置き換えるのが助けになると思います。 – laiboonh

    関連する問題