Overriding a generic abstract method and calling it

Common interface:

public interface Matcher<T> { public double getScore(T value1, T value2); } 

Two implementing classes:

 public StringMatcher implements Matcher<String> { public double getScore(String value1, String value2) {...} } public DateMatcher implements Matcher<Date> { public double getScore(Date value1, Date value2) {...} } 

So far so good. Replacing T with String or Date not a problem. Calling the getScore() method as follows also works:

 Matcher<String> matcher = new StringMatcher(); matcher.getScore("hello", "world"); 

The problems begin when I have a List an unknown Matcher , and I want to use the getScore() method.

 public void test() { List<Matcher<?>> list = new ArrayList<Matcher<?>>(); list.add(new StringMatcher()); list.add(new DateMatcher()); for (Matcher<?> matcher : list) { Object value1; Object value2; //Setting values value1 & value2 appropriate to the current matcher matcher.getScore(value1, value2); } } 

I cannot call matcher.getScore(value1, value2) , because it cannot handle object parameters. And now I have no idea how to solve this. I want to keep the interface and the signatures of the implementation classes with their specific types. If there are no methods associated with type casting or throwing exceptions, that is ok.

+4
source share
2 answers

You represent a conflict between the desire for type safety and you don't want it, so you just need to resolve between them. Calling getScore with arguments to Object clearly unsafe.

Now, if you just need an unsafe type trick to get around compiler / runtime errors, you can declare the list as a List<Matcher> , which means you will extract raw Matcher from it allowed to pass Object in. However, you will receive a warning compiler warning.

+8
source

It would be better to use the capture helper, so you can use the somater parameter type (say T ), and value1 and value2 will be declared such types of T

 private <T> double helper(Matcher<T> matcher) { T value1; T value2; //Setting values value1 & value2 appropriate to the current matcher return matcher.getScore(val1, val2); } public void test() { List<Matcher<?>> list = new ArrayList<Matcher<?>>(); list.add(new StringMatcher()); list.add(new DateMatcher()); for (Matcher<?> matcher : list) { helper(matcher); } } 
0
source

All Articles