用通用签名覆盖抽象方法并调用它

时间:2012-12-24 21:02:39

标签: java generics

通用接口:

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

两个实施类:

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

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

到目前为止一切都很好。用TString替换Date不是问题。 按如下方式调用getScore()方法也有效:

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

当我有List未知Matcher并且我想使用getScore()方法时,问题就开始了。

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

我无法调用matcher.getScore(value1, value2),因为它无法处理对象参数。 在这一点上,我不知道如何解决这个问题。我想保持实现类的接口和签名及其具体类型。如果无法进行类型转换或抛出异常,那就没关系。

2 个答案:

答案 0 :(得分:8)

你想要类型安全而不想要它之间存在冲突,所以你只需要在它们之间做出决定。使用getScore参数调用Object显然是类型不安全的。

现在,如果您只是想要一个类型不安全的技巧来解决编译器/运行时错误,您可以将列表声明为List<Matcher>,这意味着您将从中检索原始Matcher然后,您将被允许通过Object。但获取未经检查的强制转换编译器警告。

答案 1 :(得分:0)

最好使用捕获助手,以便您可以使用匹配器的参数类型(例如T),并且value1value2将被声明为属于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);
    }
}