Как запретить доступ к методу суперкласса

Мне было интересно, как я могу запретить доступ к методу суперкласса класса?

Пример: у меня есть класс Door и класс Emptyness, который в основном является просто открытой дверью для моего приложения, теперь я хочу унаследовать большинство методов дверей, но я не хочу, чтобы пользователь мог вызывать «закрыть дверь». метод на пустоте, как я могу это сделать?


person Samuel    schedule 17.04.2011    source источник
comment
Сделать метод приватным?   -  person Marnix    schedule 17.04.2011
comment
Но чем пользователи не могут позвонить в дверь?   -  person Samuel    schedule 17.04.2011


Ответы (5)


Похоже, что Emptyness не прошел тест "должен ли я быть подклассом" в отношении Door. Тест заключается в том, что следующее предложение верно: Emptyness есть Door. Поскольку Door можно закрыть, Emptyness этому требованию не соответствует.

Рекомендуется использовать агрегацию, а не наследование. Пусть Emptyness реализует свой собственный интерфейс (или какой-либо другой соответствующий интерфейс, но не Door) и содержит экземпляр Door, который он использует для выполнения соответствующих операций.

Делать что-то вроде переопределения операции close, чтобы ничего не делать или генерировать исключение, совершенно неуместно, если только Door#close не определено как необязательное (через тег throws для соответствующего исключения). (И остерегайтесь «необязательных» операций в иерархиях классов, они обычно указывают на проблему проектирования. Не обязательно всегда, но обычно.) Пример, который Андреас приводит для Iterator#remove, например: Iterator#remove помечен как бросающий UnsupportedOperationException. Если Door#close помечен таким образом, и если вас устраивает такой способ ведения дел, отлично, вы там. Но если это не так, то Emptyness не выполняет контракт Door, что обычно означает, что вам нужно пойти другим путем.

person T.J. Crowder    schedule 17.04.2011

Очевидно, что мы не можем уменьшить видимость при переопределении метода. Если метод закрытия двери в Door равен public, переопределенный метод в Emptyness не может быть закрытым...

Обычный подход состоит в том, чтобы переопределить метод close door в Emptyness и просто ничего не делать или выкинуть какой-нибудь UnsupportedOperationException (как это делают разработчики Iterator, если они не позволяют удалить элемент).

Пример:

 public class Door {
   public void closeDoor() {
     // closing door actions
   }
 }

 public class Emptyness extends Door {
   @Override void closeDoor() {
     // do nothing or
     throw new UnsupportedOperationException("Can't close door on Emptyness");
   }
 }
person Andreas Dolk    schedule 17.04.2011

Почему бы не использовать шаблон конструктора. Так как метод closeDoor не является общим для всех подклассов Door, то его вообще не должно быть в классе Door, лучше сделать интерфейс с именем Closable с методом close, реализовать этот интерфейс в некоторых классах, таких как ClosableTrue и ClosableFalse. Теперь создайте ссылочную переменную в классе Door типа Closable и инициализируйте ее в конструкторе класса объектом ClosableTrue или ClosableFalse в зависимости от типа аргумента, переданного конструктору. Теперь всякий раз, когда метод close вызывается для любого объекта Door или подкласса Door, будет вызываться метод, чей класс использовался для инициализации конструктора Door. Вы можете реализовать метод close класса ClosableFalse без какой-либо значимой функциональности.

person Lavneesh    schedule 17.04.2011

Сделайте это приватным в классе Door. Потому что, если у вас есть общедоступный или защищенный в суперклассе, вы не можете иметь более ограничительный модификатор доступа в нисходящей иерархии. Таким образом, вы не можете сделать приватным в классе Empty, скорее вы должны сделать это в классе Door.

person GuruKulki    schedule 17.04.2011

Есть много вариантов. Выберите то, что соответствует вашим потребностям

  1. Сделайте метод private
  2. Сделайте метод final таким, чтобы его нельзя было переопределить, а также добавьте логику, проверяющую, вызывается ли метод из instanceof Пустоты, а затем генерируйте исключение.

     public class Emptiness extends Door{
    
    
            public static void main(String[] args) throws Exception {
                Door x = new Emptiness();
                x.somemethod();
            }
    
        }
    

    Класс двери

    public class Door {         
            final public void somemethod() throws Exception{
                if(this instanceof Emptiness){
                    throw new Exception();
                }
            }
        }
    
person Abhishek    schedule 17.04.2011
comment
Честно говоря, мне это не нравится - класс не должен реализовывать функциональность, которая явно и исключительно принадлежит подклассу - в данном случае: Пустота не может закрыть дверь. - person Andreas Dolk; 17.04.2011
comment
Я тоже. Он компилируется, но не является ООП. Виноват - person Abhishek; 17.04.2011