2010-08-13 4 views
16

J'ai vu plusieurs questions Scala récemment (par exemple here, here, et here) qui appelaient à l'utilisation de proxies, et cela est apparu plus d'une fois dans mon propre travail. La bibliothèque Scala a un certain nombre de traits de substitution (14, si j'ai compté correctement).Proxies/délégués dans Scala

classes Proxy/traits contiennent généralement beaucoup de passe-partout:

class FooProxy(val self: Foo) extends Foo { 
    // added behavior 
    def mymethod = ... 

    // forwarding methods 
    def method1 = self.method1 
    def method2(arg: String) = self.method2(arg) 
    ... 
} 

trait Foo { 
    def method1: Unit 
    def method2(arg: String): Unit 
} 

Ma première pensée a été de définir un trait Proxy[T] qui pourrait être utilisé comme suit:

class FooProxy(val self: Foo) extends Proxy[Foo] { 
    // added behavior 
    def mymethod = ... 
} 

trait Proxy[T] extends T. Bien sûr, il n'est pas vraiment possible de définir le trait Proxy sans la magie du compilateur.

Ma pensée suivante était de chercher un plugin compilateur (une telle capacité est clairement pas dans le compilateur existant ou les sources de ces 14 traits de proxy serait beaucoup plus faible). Effectivement, j'ai trouvé Kevin Wright's AutoProxy plugin. Le plugin est destiné à résoudre le problème de proxy soigneusement, ainsi que d'autres cas d'utilisation (y compris mixins dynamiques):

class FooProxy(@proxy val self: Foo) { ... } 

Malheureusement, il semble que le travail sur elle en Novembre au point mort (2009). Donc, mes questions sont

  1. Y a-t-il un travail continu sur le plugin AutoProxy?
  2. Est-ce que cela trouvera son chemin dans le compilateur?
  3. D'autres approches sont-elles envisagées?
  4. Enfin, cela montre-t-il une faiblesse significative dans Scala? Après tout, ne serait-il pas possible de définir un trait Proxy donné des macros de style lisp?
+0

Les caractères ne peuvent pas avoir de paramètres. Proposez-vous qu'ils soient ajoutés? De plus, vous n'avez rien montré qui ne puisse être corrigé avec l'ajout d'une conversion implicite. La proposition de créer une conversion implicite est-elle inutile? –

+0

"Les caractères ne peuvent pas avoir de paramètres": erreur stupide, corrigé. –

+0

Les conversions implicites résolvent des problèmes similaires, mais elles ne sont pas toujours appropriées (sinon pourquoi les gars de l'EPFL incluraient-ils autant de proxies dans la bibliothèque Scala?). Pour un, ils encourent plus de frais généraux que la délégation. Deuxièmement, l'utilisation extensive de la conversion implicite peut nuire à la maintenabilité/lisibilité. –

Répondre

6

Quatre questions, quatre réponses

  1. Je suis, bien que la famille doit venir en premier! Plus les autres sont impliqués dans l'examen du problème général avec les méthodes de synthèse dans un plugin de compilateur.

  2. Si oui, il sera très probablement sous une forme différente, peut-être sans utiliser des annotations.

  3. Je ne sais pas de tout plug-ins équivalents, bien que l'un des projets candidats Scala GSOC se fondait en partie sur mon code autoproxy. Il y a, cependant, une solution très propre qui fonctionnera dans la plupart des cas et qui n'a pas du tout besoin d'un plugin de compilation: Vous définissez une conversion implicite de FooProxy à Foo qui retourne simplement le membre self; Cela vous permettra d'aller le plus loin possible. Les principaux problèmes avec l'approche sont que cela va rendre la vie plus difficile si vous avez besoin d'utiliser votre code de Java, il peut être moins efficace en termes de vitesse/mémoire, et c'est une autre imlicit que vous devez connaître.

  4. La partie frustrante est que la quasi-totalité de la logique nécessaire est déjà disponible dans le compilateur, et il est utilisé pour mixins, donc il vraiment devrait être une façon élégante de gérer la tâche.

+0

Découvrez la transformation @Delegate AST dans Groovy. C'est vraiment sympa. http://docs.codehaus.org/display/GROOVY/Delegate+transformation – sourcedelica

5

Adam Warski recently blogged à propos a Macro-based approach qui peuvent travailler dans Scala 2.11 et fonctionne certainement avec le plugin compilateur Paradise Macro Scala 2.10.

Cette bibliothèque vous permettra d'écrire

class FooProxy(@delegate wrapped: Foo) extends Foo { 
    // added behavior 
    def mymethod = ... 

    // forwarding methods (generated for you) 
    // def method1 = wrapped.method1 
    // def method2(arg: String) = wrapped.method2(arg) 
} 

Le projet est très tôt, la preuve de concept, stade au moment où nous écrivons ces lignes, si la prudence est justifiée.