让编译器通过重载方法来完成工作并不起作用

时间:2014-04-09 12:21:32

标签: java compiler-construction overloading strong-typing

假设我有以下类结构

public interface Searchable{

    public boolean matches(String text);

}

public abstract class AbstractSearchable implements Searchable{

    private String name;


    public boolean matches(String text){
        return null != name && name.startswith(text);
    }
}

我的大多数域对象都继承自AbstractSearchable,但有一些只有Searchable并且实现了自己的行为。

然后我有一个测试如下:

public class SearchableTest<T extends Searchable>{
    public void testSearchable(){
        //get an instance which is either Searchable or AbstractSearchable
        T item = getSomeTestItem();
        checkItem(item);
    }

    public void checkItem(Searchable searchable){
        throw new UnsupportedOperationException("Please implement your own check for Searchable and Override checkItem(Searchable)!");
    }

    public void checkItem(AbstractSearchable item){
        //here i can Implement the Test using the name from AbstractSearchable
        //... implementation
    }
}

我认为,如果getSomeTestItem的返回是AbstractSearchable,编译器会发现它并将其传递给'right'checkItem方法。我在某处阅读(我真的忘了在哪里),Java编译器总是想出“最适合”的类型(意思是TestItem实际上比搜索更“抽象”)。不幸的是,它没有,并且所有AbstractSearchables都被传递给'错误的'checkItem`方法。

我知道quickfix

public void checkItem(Searchable searchable){
    if (searchable instanceof AbstractSearchable){
        checkItem((AbstractSearchable)searchable);
    } else {
        throw new UnsupportedOperationException("Please implement your own check for Searchable and Override checkItem(Searchable)!");
    }
}

但我真的讨厌instanceof次检查。我有什么办法可以做到这一点吗?

2 个答案:

答案 0 :(得分:2)

正如您所说编译器试图找到最合适的 - 但getTestItem返回的对象类型只会在运行时被识别,您只能将其声明为{{ 1}}。因此,您在编译时可以找到的最佳拟合是T extends Searchable: - (

答案 1 :(得分:0)

对于所需的类结构,我认为没有办法达到你想要的,因为T被声明为extends Searchable,可以是SearchableAbstractSearchable ,并根据此信息找到正确的方法,即您描述和不想要的行为。

为了避免此问题,您可能希望重构类以避免继承AbstractSearchable,而是委托matches()调用提供给域对象或服务中的某些实现。< / p>