2010-09-01 6 views
2

Mon implémentation d'une méthode getHandler, qui est définie sur une interface Java, a échoué, et je ne sais pas pourquoi. Voici la signature de la méthode:Implémentation d'une méthode d'interface Java dans Scala

<H extends EventHandler> H getHandler(Type<H> type, int index); 

Ma mise en œuvre Scala est:

def getHandler[H <: com.google.gwt.event.shared.EventHandler] 
    (aType: Type[H], index: Int): H 
    = new com.google.gwt.event.shared.EventHandler() {} 

... mais le compilateur me donne ce message:

type mismatch; 
    found: java.lang.Object with com.google.gwt.event.shared.EventHandler 
    required: H 

Où ai-je commis une erreur?

Répondre

1

Je pense que cela peut faire la compilation:

def getHandler[H <: com.google.gwt.event.shared.EventHandler] 
    (aType: Type[H], index: Int): H = { 
    val h = new com.google.gwt.event.shared.EventHandler() {} 
    h.asInstanceOf[H] 
} 

Il est attend un H. Comme Lachlan dit, aType est probablement nécessaire quelque part.

+0

... et encore plus succinctement: nouveau com.google.gwt.event.shared.EventHandler() {}. AsInstanceOf [H] – David

+0

Il pourrait le faire compiler, mais c'est un conseil terrible. Le code est incorrect et entraînera des problèmes s'il est implémenté de cette façon. –

+1

Oui, je suis d'accord, comme conseil c'est terrible. J'ai regardé http://www.docjar.com/html/api/com/google/gwt/event/shared/HandlerManager.java.html et j'ai décidé que j'allais simplement répondre pourquoi il ne compile pas. Je me sens mal c'est la réponse acceptée. – huynhjl

4

Je pense que c'est parce que votre implémentation ne respecte pas le contrat de l'interface. H peut être tout sous-type de EventHandler, déterminé par le type de l'argument aType. Mais votre implémentation retourne toujours le même sous-type anonyme de EventHandler, indépendamment de ce qui est passé comme l'argument aType.

Je ne sais pas quelle serait une implémentation correcte, mais je ne vois pas comment cela pourrait être implémenté sans utiliser le paramètre aType.

3

Ajoutant à Lachlan's answer Je voudrais préciser que le simple fait de convertir le type de retour au type attendu peut avoir des effets désastreux.

Tenir compte la mise en œuvre suivante où je l'ai utilisé une classe nommée au lieu de la classe interne anonyme de la question:

class MyHandlerA extends EventHandler 
class MyHandlerB extends EventHandler 

object BadImplementation extends I { 
    def getHandler[H <: EventHandler](typ : Type[H], index: Int) = { 
    (new MyHandlerA).asInstanceOf[H] // BAD: This asInstanceOf is a lie! 
    } 
} 

La ligne suivante provoquera une ClassCastException sans avertissement.

val b: MyHandlerB = BadImplementation.getHandler(new Type[MyHandlerB] {} , 0) 

Ainsi, en plus la distribution d'une mise en œuvre devra veiller à ce que le gestionnaire est retourné réellement assignable à H ou retourner null ou jeter une exception.

Questions connexes