À l'aide de traits Scala et mise en œuvre de méthodes en Java
Je suppose qu'il n'est pas possible d'invoquer des méthodes mises en œuvre dans Scala traits de Java, ou est-il un moyen?
Supposons que j'ai en Scala:
trait Trait {
def bar = {}
}
et en Java si je l'utilise comme
class Foo implements Trait {
}
Java se plaint que Trait is not abstract and does not override abstract method bar() in Trait
- Est-ce une erreur? Ne pas la ligne de ressembler à "Java se plaint de ce que Foo n'est pas abstrait et ne remplace pas la méthode abstraite bar() dans le Trait" ?
Vous devez vous connecter pour publier un commentaire.
Réponse
De perspective Java
Trait.scala
est compilé dansTrait
interface. D'où la mise en œuvre deTrait
en Java est interprété comme la mise en œuvre de l'interface qui rend vos messages d'erreur évidente. Réponse courte: vous ne pouvez pas profiter de trait implémentations en Java, car cela permettrait à l'héritage multiple en Java (!)Comment est-il mis en œuvre dans Scala?
Réponse longue: alors, comment ça marche dans la Scala? En regardant le bytecode généré/classes, on peut trouver le code suivant:
Trait
est une interfaceTrait$class
(à ne pas confondre avecTrait.class
), la classe est créée de manière transparente, ce qui techniquement n' pas mettre en œuvreTrait
interface. Il est cependant doté d'unstatic bar()
méthode de prise deTrait
exemple comme argument (sorte dethis
)Foo
implémenteTrait
interfacescalac
implémente automatiquementTrait
méthodes en déléguant àTrait$class
. Cela signifie essentiellement appelTrait$class.bar(this)
.Noter que
Trait$class
est ni membre deFoo
, ni neFoo
l'étendre. Il délègue simplement en passantthis
.Mélange dans de multiples traits
Pour continuer la digression sur comment Scala fonctionne... cela étant dit, il est facile d'imaginer comment le mélange dans de multiples traits fonctionne sous:
se traduit par:
Plusieurs traits de caractère primordial même méthode
Maintenant, il est facile d'imaginer comment le mélange de plusieurs traits de caractère primordial même méthode:
Nouveau
Trait1
etTrait2
deviendra interfaces extensionTrait
. Maintenant, siTrait2
est à la dernière place lors de la définition deFoo
:vous obtiendrez:
Cependant commutation
Trait1
etTrait2
(prise deTrait1
être le dernier) se traduira par:Empilables modifications
Considérons maintenant comment les traits de cumul des modifications de travail. Imaginez avoir vraiment utile en classe Foo:
qui vous souhaitez enrichir avec de nouvelles fonctionnalités à l'aide de traits:
Voici le nouveau " Foo " sur les stéroïdes:
Il se traduit par:
Trait1
Trait2
FooOnSteroids
Donc l'ensemble de la pile invocations sont comme suit:
Et le résultat est "Foo, Trait1, Trait2".
Conclusion
Si vous avez réussi à tout lire, une réponse à la question d'origine est dans les quatre premières lignes...
abstract override
fonctionne, mais il est très bon sinon. 🙂class Foo implements Trait1, Trait2
à nouveau lorsque vous prévu pour passer Trait1 et Trait2.Il est en effet rien d'abstrait puisqu'
bar
est de retourner un videUnit
(une sorte de NOP). Essayez:Puis
bar
sera un Java méthode abstraite retourvoid
.bar
deTrait
, je voudrais le réutiliser dans une classe Java, comme je peux le faire en Scala. Mais je suppose que cela n'est pas possible. La seule solution semble être de convertir Trait dans une classe abstraite.