2010-11-18 7 views
3

Je veux trouver un moyen de définir une nouvelle méthode dans une classe existante dans scala.Injecter des méthodes dans des classes existantes

Par exemple, je pense que la méthode asInstanceOf[T] a trop longtemps un nom, je veux le remplacer par as[T].

Une approche avant droit peut être:

class WrappedAny(val a: Any) { 
    def as[T] = a.asInstanceOf[T] 
} 

implicit def wrappingAny(a: Any): WrappedAny = new WrappedAny(a) 

Y at-il une manière plus naturelle avec moins de code?

En outre, une chose étrange se produit lorsque je tente ceci:

scala> class A 

defined class A 

scala> implicit def toA(x: Any): A = x 

toA: (x: Any)A 

scala> toA(1) 

Et la console hang. Il semble que toA(Any) ne devrait pas passer la phase de vérification de type, et il ne peut pas quand il n'est pas implicite. Et mettre tout le code dans un code source externe peut produire le même problème. Comment est-ce arrivé? Est-ce un bug du compilateur (version 2.8.0)?

Répondre

8

Il n'y a rien de mal techniquement dans votre approche du proxénétisme Any, bien que je pense que c'est généralement mal avisé. De même, il y a une raison asInstanceOf et isInstanceOf sont si verbeusement nommé; c'est pour vous décourager de les utiliser! Il y a presque certainement une meilleure façon de faire ce que vous essayez de faire.

En ce qui concerne l'exemple qui provoque votre console pour accrocher: le type déclaré de toA est Any => A, mais vous avez défini le résultat comme x, qui est de type Any, pas A. Comment cela peut-il compiler? Eh bien, rappelez-vous que lorsqu'une erreur de type apparente se produit, le compilateur recherche toutes les conversions implicites disponibles pour résoudre le problème. Dans ce cas, il faut une conversion implicite Any => A ... et en trouve une: toA! Ainsi, les contrôles de type raison toA est parce que le compilateur est en train de redéfinir implicitement comme:

implicit def toA(x: Any): A = toA(x) 

... qui des résultats de cours dans une récursion infinie lorsque vous essayez de l'utiliser.

+0

Wow! Ceci est incroyable. Comment avez-vous eu cette idée? Et de plus, l'asInstanceOf [T] n'est qu'un exemple. Je suis juste curieux qu'il y ait de la syntaxe pour travailler dans le cas général. –

+0

En règle générale, s'il y a évidemment une erreur de type dans votre code mais que le compilateur l'accepte, il y a une conversion implicite au travail ... ça et le fait qu'il soit suspendu étaient les indices majeurs :) –

3

Dans votre deuxième exemple, vous transmettez Any à une fonction qui doit renvoyer A. Cependant, il ne retourne jamais A mais le même Any vous avez passé. Le compilateur essaie alors d'appliquer la conversion implicite qui à son tour ne renvoie pas un A mais Any, et ainsi de suite.

Si vous définissez Toa que vous obtenez ne pas être implicite:

scala> def toA(x: Any): A = x   
<console>:6: error: type mismatch; 
found : Any 
required: A 
     def toA(x: Any): A = x 
          ^
1

Comme il arrive, cela a été discuté sur les listes Scala avant. Le modèle de ma classe de proxénète est en effet un peu verbeux pour ce qu'il fait, et, peut-être, il pourrait y avoir un moyen de nettoyer la syntaxe sans introduire de nouveaux mots-clés. Le point sur les nouveaux mots-clés est que l'un des objectifs de Scala est de rendre le langage évolutif à travers les bibliothèques, au lieu de transformer le langage en une courtepointe géante d'idées qui répondent aux critères de «suffisamment pour ajouter au langage». , en même temps, rendant d'autres idées impossibles parce qu'elles n'étaient pas jugées utiles et/ou assez communes.

Quoi qu'il en soit, rien n'est arrivé jusqu'à présent, et je n'ai pas entendu dire qu'il y avait du travail en cours pour atteindre cet objectif.Vous êtes invités à rejoindre la communauté à travers ses listes de diffusion et à contribuer à son développement.

Questions connexes