aleclerc
aleclerc

Reputation: 707

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?

Upvotes: 39

Views: 59275

Answers (7)

fastcodejava
fastcodejava

Reputation: 41097

IMO it would be cleaner if you do this :

public void sendNotification( IMech mechanism ){
}

You can always get the class inside the method.

Upvotes: 1

chandler newman
chandler newman

Reputation: 39

the correct way is:

public void sendNotification(IMech mechanism) {

}

so please read some java tutorials about interfaces everyone!

Upvotes: 3

Powerlord
Powerlord

Reputation: 88796

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.

Upvotes: 3

rwhit
rwhit

Reputation: 89

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.

Upvotes: 5

corsiKa
corsiKa

Reputation: 82559

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.

Upvotes: 1

Mike Daniels
Mike Daniels

Reputation: 8642

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>.

Upvotes: 10

axtavt
axtavt

Reputation: 242686

Perhaps you need

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

Upvotes: 56

Related Questions