2010-05-18 8 views
33

Ich habe eine Schnittstelle:Passing Interface-Klasse als Parameter in Java

public interface IMech { 

} 

und eine Klasse, die es

public class Email implements IMech { 

} 

und eine dritte Klasse implementiert, die diese Methode implementiert hat:

public void sendNotification(Class<IMech> mechanism){ 
} 

jetzt versuche ich, diese Methode so zu nennen

foo.sendNotification(Email.class); 

, aber ich erhalte eine Ausnahme zu sagen:

The method sendNotification(Class<IMech>) in the type RemediationOperator is not applicable for the arguments (Class<Email>) 

Sollte das nicht funktionieren, wenn es diese Klasse Schnittstellen?

+1

Was ist die EmailNotification Klasse und was implementiert oder erweitert sie? –

+0

Wollen Sie wirklich die Klasse Objekt zu übergeben, nicht eine Instanz einer Klasse, die die IMech Schnittstelle implementiert? Das könnte sicher sein, was Sie wollen, aber ich kann aus den Angaben nicht sagen, Sie zur Verfügung gestellt, ob es absichtlich oder ein Design-Fehler. –

+0

Sorry, ich auf einige Klassennamen verkürzt hatte ... ist EmailNotification die E-Mail-Klasse – aleclerc

Antwort

48

Vielleicht brauchen Sie

public void sendNotification(Class<? extends IMech> mechanism) { 
3

Generics nicht auf diese Weise in Java arbeiten. Was Sie wirklich tun müssen, um es die Methodensignatur

public void sendNotification(Class< ? extends IMech > mechanism){ 
} 

ändern Oder ist das super statt extends ... lassen Sie mich Generics chapter Effective Java konsultieren ...

Edit: Effective Java sagt:

hier ein mnemonic ist Sie erinnern zu helfen, die Wildcard-Typ zu verwenden: PECS steht für hersteller erstreckt, Verbraucher-sup er.

Ich gehe davon aus das wird IMech Fällen produzieren, und dass extends korrekt ist.

10

Da die beiden Klassen Class<IMechanism> und Class<EmailNotification> selbst sind nicht von inheritence bezogen, obwohl IMechanism und EmailNotificationsind.

Sie müssen Ihre Methode akzeptieren eine Class<? extends IMechanism>.

1

Die Idee hinter Schnittstellen ist, dass Sie nicht wissen müssen, welcher es ist. Sie sollten einfach in der Lage sein, ein IMech zu übergeben und seine Funktionalität unabhängig von der Implementierung aufzurufen. Berücksichtigen Sie Folgendes:

public interface IMech { 
    void sendMessage(); 
} 

public class Email implements IMech { 
    @Override 
    void sendMessage() { /* stuff here to send email */ } 
} 

Das ist das typische Verwendungsmuster für eine Schnittstelle. Wenn Sie es nur für eine Option verwenden, sollten Sie stattdessen eine Enumeration verwenden.

enum IMech { EMAIL, INSTANT_MESSAGE, SNAIL_MAIL, YELL_OVER_CUBICLE } 

public void sendNotification(IMech mechanism){ 
    switch(mechanism) { 
     case IMech.EMAIL: // do email .. etc 
    } 
} 

foo.sendNotification(IMech.EMAIL); 

Jetzt weiß ich, diese Fragen beantworten nicht direkt, aber das sind die typischen Formen der Nutzung, und sind in der Regel von anpassungsfähiger Designmuster indikativ. Muss man wirklich ein Klassenobjekt einsenden? Ein Enum erscheint geeigneter, wenn Sie nur bestimmen, welcher Mechanismus verwendet werden soll.

5

Ihre Parameter Mechanismus muss eine beschränkte Platzhalter verwenden, etwa so:

public void sendNotification (Klasse < erstreckt IMech> Mechanismus?) { }

das Tutorial Generika Zitiert link text

Im allgemeinen, wenn Foo ist ein Subtyp (Unterklasse oder Subschnittstelle) von Bar und G ist einige generische Typdeklaration, es ist nicht der Fall, dass G ein Subtyp von G. ist

3

der richtige Weg ist:

public void sendNotification(IMech mechanism) { 

} 

so wenden Sie sich bitte einige Java-Tutorials über Schnittstellen alle lesen!

1

IMO wäre es sauberer sein, wenn Sie dies tun:

public void sendNotification(IMech mechanism){ 
} 

Sie können jederzeit die Klasse innerhalb der Methode erhalten.