Différence entre ceci et soi dans les annotations auto-types?

134

Dans diverses publications Scala, je vois des annotations auto-types utilisant "this" et d'autres utilisant "self":

trait A { this: B => ... }
trait A { self: B => ... }

Y a-t-il une réelle différence entre utiliser «ceci» ou «soi»? Le nom que vous utilisez importe-t-il? Est-ce tout aussi valable?

trait A { foo: B => ... }
Zach
la source

Réponses:

181

Les trois formulaires sont valides et ont l'effet qui Best supposé être le type de thisen classe A.

Les deux premières variantes

trait A { self: B => ... }
trait A { foo: B => ... }

introduire self(respectivement, foo) comme alias pour thisin trait A. Ceci est utile pour accéder à la thisréférence à partir d'une classe interne. C'est-à-dire que vous pouvez alors utiliser selfau lieu de A.thislors de l'accès à la thisréférence du trait à Apartir d'une classe imbriquée en son sein. Exemple:

class MyFrame extends JFrame { frame =>    
  getContentPane().add( new JButton( "Hide" ) {
    addActionListener( new ActionListener {
      def actionPerformed( e: ActionEvent ) {
        // this.setVisible( false ) --> shadowed by JButton!
        frame.setVisible( false )
      }
    })
  })
}

La troisième variante,

trait A { this: B => ... }

n'introduit pas d'alias pour this; il définit simplement le type de soi.

Martin Odersky
la source
La façon dont je regarde le type de soi est que le trait s'est déclaré comme prenant un certain type et retournant le bloc de code, par exemple foo: B => {...}. Maintenant, ces boucles sont bien sûr omises. Il est intéressant de voir que vous pouvez utiliser le nom de l'objet au lieu de "this" dans n'importe quelle portée du code bien que [quelque chose que nous faisons tout le temps en javascript]
Ustaman Sangat
4
@Martin Odersky Est-il possible d'ajouter une restriction pour deux ou plusieurs traits, quelque chose comme trait A { self: B, C => ... }?
Dmitry Bespalov
13
@DmitryBespalov: Oui, vous pouvez utiliser le withmot - clé dans l'annotation à saisie automatique. Par exempletrait A { self: B with C => ... }
Dave
btw, vous pouvez également le faire _: B =>pour le cas de non-alias pour plus de simplicité
Creos
17

Il y a une différence en ce que thisfait toujours référence à l'objet défini par le modèle le plus interne.

L'expression thispeut apparaître dans la partie instruction d'un modèle ou d'un type composé. Cela signifie que l'objet est défini par le modèle le plus profond ou le type composé entourant la référence. S'il s'agit d'un type composé, le type de thisest ce type composé. Si elle est un modèle d'une définition de classe ou d'un objet avec nom simple C , le type de c'est le même que le type de C . this. (Scala Réf. §6.5)

Donc, si vous appelez votre self-type foo, vous pouvez toujours vous y référer comme this(à moins, bien sûr, que vous soyez dans un modèle interne auquel cas thisse référera à l'objet défini par celui-ci - et à moins que vous ne donniez le modèle saisit le même nom) mais évidemment pas l'inverse.

Debilski
la source