Есть ли способ избежать наложения этого типа?
Рассмотрим следующий класс, который определяет и реализует Foo
интерфейс:
public class MyClass {
public Foo getFoo() {
return new FooImpl();
}
public void fooMethod(Foo foo) {
final fooImpl = (FooImpl) foo;
fooImpl.hiddenMethod();
}
public interface Foo {
void doSomething();
}
private class FooImpl implements Foo {
public void doSomething();
void hiddenMethod() {
}
}
}
Вне классов будут звонить MyClass.getFoo()
чтобы получить Foo
объект и может передать его обратно fooMethod()
, fooMethod()
ожидает FooImpl
реализация Foo
и бросает Foo
в FooImpl
так что он может вызвать метод package-private hiddenMethod()
,
Мой вопрос, я не без ума от кастинга Foo
в FooImpl
, Есть ли другой шаблон, который я могу использовать, чтобы сделать то же самое?
Заранее спасибо...
3 ответа
Проблема здесь в том, что вы неявно нарушаете принцип инкапсуляции. В вашем классе есть метод, который зависит от реализации и, следовательно, не является частью интерфейса Foo. Это нарушение принципов ОО, этот актерский состав - только вершина айсберга. Что если вы хотите создать новый класс реализации Foo, в котором нет методов, которые вы хотите вызвать?
Вам следует переделать свой код, чтобы можно было вызывать только методы из интерфейса Foo.
Вы можете добавить hiddenMethod
метод к Foo
интерфейс
public interface Foo {
...
void hiddenMethod();
}
Поскольку интерфейс является контрактом для поддерживаемых операций, вам не нужно (не нужно?) Приводить объект для доступа к методам вне интерфейса.
Вы должны быть удручены.
Делай так
public void fooMethod(Foo foo) {
if(foo instanceof FooImpl){
final FooImpl fooImpl = (FooImpl) foo;
fooImpl.hiddenMethod();
}
}
Супер тип не может быть понижен без явного снижения. Не забудьте проверить его перед использованием instanceof
оператор.
--РЕДАКТИРОВАТЬ--
Сделайте еще одну вещь, если хотите избежать кастинга. добавлять hiddenMethod()
в Foo
Интерфейс также.
public interface Foo {
void doSomething();
void hiddenMethod();
}