Question

Suppose I have the following class Structure

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

Most of my domain Objects inherit from AbstractSearchable, but there are a few which are only Searchable and implement their own behavior.

Then I have a Test as Following:

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

I thougth, that if the Return of getSomeTestItem is AbstractSearchable the compiler will find this out and passes it to the 'right' checkItem method. I read somewhere ( I really forgot where), taht the Java compiler always figures out kind of the 'best fit' (meaning TestItem is actually 'more' AbstractSearchable than Searchable). Unfortunately it does not, and all AbstractSearchables gets passed to the 'wrong' checkItem` method.

I'm aware of the 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)!");
    }
}

but I really hate instanceof checks. Is there something I can do, to make this work?

Was it helpful?

Solution

As you say the compiler tries to find the best fit - but the kind of object returned by getTestItem will only be known at runtime and you only declare it to be a T extends Searchable. So the best fit you can find at compile-time is checkItem(Searchable searchable) :-(

OTHER TIPS

For the desired class structure I think there is no way to achieve exactly what you want, because T is declared as extends Searchable, which can be Searchable or AbstractSearchable, and the proper method will be found based on this information, i.e. the behavior you described and do not want.

In order to avoid this problem, you might want to refactor your classes to avoid inheritance of AbstractSearchable and instead delegate matches() calls to some implementation provided to domain object, or maybe in the service.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top