2014-09-19 6 views
1

У меня 3 класса.Как скрыть метод родительского интерфейса в Java?

public interface Operation { 
    void move(); 
    void delete(); 
    void search(String criteria); 
} 

public abstract class AbstractOperationProcessor implements Operation { 
    public void move() { 
     // some logic 
    } 
} 

public class DailyMailProcessor extends AbstractOperationProcessor{ 
    // need to hide this method because I don't want to provide them to customer 
    public void delete() {} 
    public void search(String criteria) {} 
} 

Что мне нужно, чтобы скрыть методы delete() и search(String) от API. Как я могу это сделать без изменения интерфейса Operation и абстрактного класса AbstractOperationProcessor?

+0

Я думаю, что вы просто не можете – Leo

+0

Вы можете повторно аннотировать методы. Это скрывает реализацию, но очевидно, что методы определены в 'интерфейсе', поэтому вы не контролируете это. –

ответ

1

Как уже было сказано, вы не можете скрыть метод суперкласса. Существует также веская причина, по которой вы не можете этого сделать: Полиморфизм позволяет передавать любой объект подтипа, где нужен объект супертипа. В вашем случае, если у вас есть метод

void foo(Operation op){op.delete()} 

можно назвать

foo(new DailyMailProcessor()) 

Как вы можете видеть, Foo не знает точный тип оп, но из-за удаления в интерфейсе Операции, то метод delete может быть вызван.

Если вам захочется удалить некоторые методы из интерфейса подтипа, вы, вероятно, не используете поведенческий подтип ! Я предлагаю вам взглянуть на Liskov Principle, что является одним из основополагающих принципов объектно-ориентированного программирования.

Если у вас есть не поведенческий подтип, вы ошибочно пытаетесь добиться повторного использования кода по наследству. Вместо этого вы должны использовать композицию. . Покровительство состав над наследования (Item 16, Effective Java) Причина в пользу композиции в вашем случае очевидна: Вы не должны бросить UnsupportedOperationException (как указано в других ответах) и тем самым получить статическую безопасность

Edit:. Для уточнения что я имею в виду, когда говорю вам использовать композицию: вместо того, чтобы класс DailyMailProcessor расширял операцию, дайте ему переменную-член типа Операции и переадресация вызовов методам, которые вы хотите поддержать переменной-члену.

public interface Operation { 
    void move(); 
    void delete(); 
    void search(String criteria); 
} 

public class DailyMailProcessor { 
    private Operation op; 
    public DailyMailProcessor {/*instantiate op*/} 
    void move() {op.move();} 
} 
+0

Какой шаблон дизайна? Это «стратегия»? – Alex

+0

Я бы сказал, что это просто композиция объекта. Но, смотря на UML-диаграмму шаблона стратегии, я думаю, вы можете посмотреть на любую композицию с интерфейсом в случае шаблона стратегии. В этом примере вы можете использовать разные «операции» -стратегии. –

9

Вы не можете. Лучшее, что вы можете сделать, это реализовать заглушки, которые бросают что-то вроде NotImplementedException и документировать этот факт.

Я бы использовал это как возможность изучить определение интерфейса верхнего уровня. Если вам нужно скрыть некоторые из его методов, то реальной проблемой может быть то, что она объединяет несвязанные функции. Возможно, вам придется разбить его на два отдельных интерфейса.

Помните, что вы можете «наследовать» (то есть реализовать) несколько интерфейсов.

+1

И даже тогда: зачем реализовывать интерфейс, если вы не собираетесь реализовывать интерфейс? –

2

Вы не можете этого сделать. Каждый метод, объявленный в интерфейсе, должен быть реализован классом. Что вы можете сделать, так это просто реализовать эти методы, но не давайте никаких определений.

1

Edit:
Как указывается в комментариях, UnsupportedOperationException может быть лучшим выбором.

Оригинальный ответ:
Существует IllegalStateException только для этого. Просто сделайте все методы, которые вы не хотите реализовывать. Просто выполните:

public class DailyMailProcessor extends AbstractOperationProcessor { 

    public void delete() { 
     throw new IllegalStateException(); 
    } 

    public void search(String criteria) { 
     // do something useful here 
    } 
} 
+3

'IllegalStateException' doc. говорит: «Сигналы о том, что метод был вызван в незаконное или ненадлежащее время». - Я предпочел бы бросить 'UnsupportedOperationException' в этом случае. – qqilihq

+0

Но это не незаконное государство. 'UnsupportedOperationException' может быть, но нет нулевой точки в реализации интерфейса, чтобы не реализовывать inteface. –

+1

@ T.J.Crowder Существуют, конечно, прецеденты - интерфейс «List » имеет операции, помеченные как «необязательные операции», которые не реализуют некоторые классы реализации. Но я думаю, что важно, чтобы документация для интерфейса маркировала их как таковую и, возможно, предоставляла логический метод для проверки того, реализована ли она, так что кто-то, кто пишет класс, который ее использует, будет знать о возможности. – ajb

0

лучшее решение, которое обрабатывать ваши problème, если, и только если вы хотите иметь его в ELEGANTE образом, является использование системы компонентов и она будет выглядеть некоторых это так:

abstract class Component { 
abstract void perform(); 
} 

abstract class Move extends Component { 
void perform() { ... } 
} 

class AbstractOperationProcessor { 
List<Component> components; 
... 
}