views:

289

answers:

5

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<IMechanism>) in the type RemediationOperator is not applicable for the arguments (Class<EmailNotification>)

Shouldn't this work if it interfaces that class?

+6  A: 

Perhaps you need

public void sendNotification( Class<? extends IMech> mechanism ) { 
axtavt
+1  A: 

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.

R. Bemrose
+3  A: 

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

Mike Daniels
+1  A: 

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.

glowcoder
+1  A: 

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.

rwhit