У меня есть интерфейс Java, например
public interface Filter{
public boolean acceptData(IFilterData data);
}
public interface IFilterData{
}
Почему Java не позволяет мне иметь класс реализации, как показано ниже?
public class SampleFilterImpl{
public boolean acceptData(SampleFilterData data){
return true;
}
}
где SampleFilterData
implements
IFilterData
Я согласен с контрактом, который указан интерфейсом фильтра прямо? Но в чем логика, почему это не позволяет мне это делать?
Я согласен с контрактом, который указан интерфейсом фильтра прямо?
Неа.
Интерфейс позволяет абонентам передавать любую реализацию IFilterData
.
Ваш класс принимает только одну конкретную реализацию.
Предполагая, что вы имели в виду
public class SampleFilterImpl implements Filter {
потому что вы могли бы
Filter filter = (flag) ? new SampleFilterImpl() : new SomeOtherFilterImpl();
filter.acceptData(new SomeOtherFilterData()); // not SampleFilterData
Если flag
был true
и filter
ссылался на объект типа SampleFilterImpl
, то вы должны передать аргумент типа SomeOtherFilterData
который не будет соответствовать типу параметра SampleFilterData
.
Нет, вы не соглашаетесь с интерфейсом Filter
. Интерфейс Filter
указывает, что вы можете передать IFilterData
в экземпляр Filter
, что означает, что вы сможете это сделать:
public class SomeOtherFilterData implements IFilterData { ... }
new SampleFilterDataImpl().acceptData(new SomeOtherFilterData());
Однако ваша acceptData
позволяет acceptData
только SampleFilterData
, что нарушает контракт.
Более общий принцип подписи Лискова гласит, что вы можете только ослабить предпосылки и/или укрепить постусловия интерфейса. В Java это означает, что вы можете использовать под-классы для типа возвращаемого значения и типы исключенных исключений переопределенного метода или бросать меньше типов исключений.
Одним из решений было бы сделать ваш Filter
общим:
public interface Filter<T extends IFilterData> {
public boolean acceptData(T data);
}
и имеют SampleFilterImpl
реализуют Filter<SampleFilterData>
. В зависимости от вашего IFilterData
использования вы можете полностью удалить IFilterData
и разрешить Filter
для любого T