2017-01-30 1 views
1

Pour les deux blocs de code, je m'attendais à ce que la référence self dans les deux blocs soit Foo [A]. Cependant, il semble que le second bloc ne compile pas. Quelqu'un peut-il m'expliquer comment résoudre les références self?Comment résoudre l'auto-référence dans ce cas?

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)) 
    } 
    } 
} 

Répondre

2

self se voir attribuer différentes this, qui est une référence à un cas particulier, celui que vous appelez une méthode (ou un constructeur) à l'invocation.

Dans le premier extrait, vous invoquez la méthode bar sur un objet de type Foo[A], ce qui signifie que, à ce moment-là this signifie l'instance de Foo[A]. Après avoir affecté this à self vous créez une nouvelle instance de Foo, cette fois en donnant un type différent au paramètre type, mais self.

Dans le second extrait, vous dites que les objets de type Foo[A] ont un champ de membre qui est appelé self et obtient attribué this. Cela s'appliquera à toutes les instances de Foo[_], quelle que soit la manière dont vous appelez le paramètre type. Lorsque vous créez un deuxième Foo appeler le paramètre de type B, cette deuxième instance aura néanmoins un champ membre self, qui obtient attribué this, qui à ce stade est Foo[B] et nuances le self que vous avez déclarés dans le cadre de la déclaration initiale de Foo.

Cela signifie que dans le second extrait, vous la mise en œuvre de la méthode format de Foo[B] a accès à une référence self de Foo[B] lui-même, ce qui provoque l'erreur de type que vous avez mentionné.

  • Foo [B] a le format de la méthode (valeur: B)
  • méthode
  • bar prend une fonction qui prend une B et la transforme en un A
  • Vous appliquez f: B => A-value: B, le transformant en un A , alors vous essayez de nourrir A à Foo[B]#format(value: B)

Désolé pour la réponse compliquée; en bref: les paramètres de type sont de simples noms d'espaces réservés pour les types réels tout comme les paramètres de valeur sont des noms d'espace réservé pour les valeurs d'exécution réelles. Appliquez le même raisonnement aux types et aux valeurs et le raisonnement à leur sujet deviendra plus facile.

+0

Bonne prise. Je me grattais la tête. 'private [this] val soi: Foo [A] = ceci' et il compile bien. – pedrofurla

+0

Merci beaucoup d'avoir pris le temps de bien expliquer cela. Je l'ai. Pour les autres qui pourraient ne pas l'obtenir, je pense qu'il est utile de substituer A et B par un temps concret avant de faire des abstractions. – laiboonh