简体   繁体   中英

Passing Interface Class as a Parameter in Java

I have an interface:

public interface IMech {

}

and a class that implements it

public class Email implements IMech {

}

and a third class that has this method implemented:

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

now I'm trying to call that method like so

foo.sendNotification(Email.class);

but i keep getting an exception saying:

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

Shouldn't this work if it interfaces that class?

也许你需要

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

Because the two classes Class<IMechanism> and Class<EmailNotification> themselves are not related by inheritence, even though IMechanism and EmailNotification are .

You need to make your method accept a Class<? extends IMechanism> Class<? extends IMechanism> .

Your parameter mechanism needs to use a bounded wildcard, like so:

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

Quoting the generics tutorial link text

In general, if Foo is a subtype (subclass or subinterface) of Bar, and G is some generic type declaration, it is not the case that G is a subtype of G.

the correct way is:

public void sendNotification(IMech mechanism) {

}

so please read some java tutorials about interfaces everyone!

Generics don't work that way in Java. What you really need to do it change the method signature to

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

Or is that super instead of extends ... let me consult Effective Java's Generics chapter ...

Edit: Effective Java says:

Here is a mnemonic to help you remember which wildcard type to use: PECS stands for producer-extends, consumer-super.

I'm assuming this will be producing IMech instances, and that extends is correct.

IMO it would be cleaner if you do this :

public void sendNotification( IMech mechanism ){
}

You can always get the class inside the method.

The idea behind interfaces is that you don't need to know which one it is. You should simply be able to pass in an IMech and call its functionality regardless of implementation. Consider the following:

public interface IMech {
    void sendMessage();
}

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

That's the typical usage pattern for an interface. If you're only using it for an option, perhaps you should consider using an enum instead.

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);

Now I know these don't directly answer your questions, but these are the typical forms of usage, and are usually indicative of more adaptable design patterns. After all, do you really need to send in a class object? An enum seems more appropriate if you're merely determining which mechanism to use.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM