Почему Java позволяет повысить видимость защищенных методов в дочернем классе?

abstract class Base{
      protected abstract void a();
}

class Child extends Base{
      @Override
      public void a(){
          //why is this valid
      }
}

Почему мы можемt уменьшить видимость, но можно ли ее увеличить?

Также мне нужно реализоватьШаблон в котором видимые публичные методы могут быть только базового класса.

Пример:

abstract class Base{
      public void callA(){
      //do some important stuff
      a();
      }

      protected abstract void a();
}

class Child extends Base{
      @Override
      public void a(){
          //why is this valid
      }
}

Теперь, если Java позволяет увеличить видимость, то есть два метода, видимых публично ??

Я знаю, что интерфейс - это одно из решений, но есть ли другой выход ???

Ответы на вопрос(4)

Поскольку Java допускает ссылку на класс Super для указания на объект подкласса. Таким образом, ограничение не должно быть увеличено сcompile-time вruntime..

Давайте рассмотрим это на примере:

public class B {
    public void meth() {

    }
}

class A extends B {
    private void meth() {  // Decrease visibility.

    }
}

Теперь вы создаете объект классаA и назначьте ему ссылку классаB.. Давайте посмотрим, как: -

B obj = new A();  // Perfectly valid.

obj.meth();  // Compiler only checks the reference class..
             // Since meth() method is public in class B, Compiler allows this..
             // But at runtime JVM - Crashes..

Теперь, так какcompiler только проверяеттип ссылочной переменнойи проверьте видимость методов в этом классе(класс Б), и этоБезразлично»проверить, что за объект делаетreference obj ссылается на .. Итак, его это не беспокоит .. Это оставлено JVM во время выполнения для разрешения подходящего метода ..

Ново время выполненияJVM на самом деле будет пытатьсявызыватьmeth метод классаA как объект класса А. Но теперь, что происходит ...BooooOOMM ---> Сбои JVM.. так какmeth метод является частным вclass A...

Тот'почему видимость не может быть уменьшена ..

Если базовый класс дает обещание относительно видимости, то подкласс не может нарушить это обещание и все еще удовлетворяет принципу замены Лискова. Вы можете't использовать подкласс в любой ситуации, где обещанный метод выставлен, если это обещание нарушено.

Подкласс IS-A базовый класс. Если базовый класс предоставляет метод, то и подкласс должен.

Там'нет выхода в Java или C ++. Я'Я думаю, то же самое верно и в C #.

 duffymo08 окт. 2012 г., 13:36
Один вопросительный знак на вопрос подойдет. Я думаю "нет» должно быть достаточно легко понять. Вы не можете сделать метод менее видимым в дочернем элементе, чем в родительском. Пусть компилятор скажет вам ответ. Это'лучше, чем прийти сюда и спросить.
 duffymo08 окт. 2012 г., 13:48
Какие'проблема? Ребенок может выбрать методБольше видимый, чем его родитель, но он не может сделать этоМеньше видимый. Это все еще удовлетворяет Лискова; это все еще ЕСТЬ-родитель; Вы можете вызвать более видимый дочерний метод a () в любом контексте, где вызывается родительский метод a ().
 Narendra Pathai08 окт. 2012 г., 13:44
простите за вопросительные знаки. но вы можете помочь мне со вторым примером, который я написал.
 duffymo08 окт. 2012 г., 13:57
Ваш второй пример не имеет смысла для меня.
 Narendra Pathai08 окт. 2012 г., 13:34
Я не'не получить ответ полностью ?? Итак, вы говорите, что я не могу ограничить дочерний класс от увеличения видимости каким-либо образом?
 Narendra Pathai08 окт. 2012 г., 13:55
да, теперь я понимаю этот принцип. но что я могу сделать, чтобы заставить этот метод базового класса выполняться, что является моей реальной проблемой! см. мой второй пример.

Почему мы можемt уменьшить видимость, но можно ли ее увеличить?

Предположим, что можно было бы уменьшить видимость. Затем посмотрите на следующий код:

class Super {
    public void method() {
        // ...
    }
}

class Sub extends Super {
    @Override
    protected void method() {
        // ...
    }
}

Предположим, что у вас был бы другой класс, в другом пакете, где вы используете эти классы:

Super a = new Sub();

// Should this be allowed or not?
a.method();

Чтобы проверить, разрешен ли вызов метода или нет, компилятор проверяет тип переменной, для которой он вызывается. Тип переменнойa являетсяSuper, Но фактический объект, которыйa относится к этоSubи там методprotected, так что вы бы сказали, что нельзя вызывать метод из несвязанного класса вне пакета. Чтобы решить эту странную ситуацию, этоЗапрещено делать переопределенные методы менее заметными.

Обратите внимание, что наоборот (делая метод более видимым) нене может привести к той же проблеме.

 Narendra Pathai08 окт. 2012 г., 13:43
Теперь я понял, спасибо. Но можете ли вы помочь мне с вопросом о методе шаблона? где мне нужно сделать некоторые важные вещи в базовом классе, и если два метода общедоступны, то я не могу сохранить контроль в базовом классе?
 supercat23 февр. 2015 г., 20:47
Семантически, не было бы проблемы, позволяющей дочернему классу скрывать родительские элементы. Код, который получает итератор, может вызватьremove на нем, поскольку вызывающая сторона может передавать только итераторы, которые поддерживают этот метод; однако, ничего не получится, если разрешить коду, который получает строго типизированную ссылку на неизменяемую коллекцию »реализация итератора для вызоваremove на этом, так как эта операция не моглаТ возможно работать. Опасность с позволениемprivate Переопределение состоит в том, что дочерний класс, возможно, намеревался создать приватную функцию, а не переопределять публичную.
Решение Вопроса

Почему снижение видимости не допускается, уже объяснено в других ответах (это нарушит контракт родительского класса).

Но почему разрешено увеличивать видимость метода? Во-первых, это не нарушило бы ни один контракт, поэтому нет никаких причин, чтобы этого не допустить. Иногда это может быть полезно, когда в дочернем классе имеет смысл не защищать метод.

Во-вторых, недопущение этого может иметь побочный эффект: иногда невозможно расширить класс и реализовать интерфейс:

interface Interface1 {
   public void method();
}

public class Parent {
   protected abstract void method();
}

public class Child extends Parent implements Interface1 {
   @Override
   public void method() {
   }
   //This would be impossible if the visibility of method() in class Parent could not be increased.
}

Что касается вашего второго вопроса, вы ничего не можете с этим поделать. Вы должны верить, что человек, который реализует дочерний класс, нене делайте ничего, что нарушает вашу реализацию. Даже если бы ява неt позволяет увеличить видимость, что все равно не решит вашу проблему, потому что можно создать открытый метод с другим именем, который вызывает абстрактный метод:

class Child extends Base{
      @Override
      protected void a(){

      }

      public void a2() {
           a(); //This would have the same problems that allowing to increase the visibility.
      }
}
 Alderath08 окт. 2012 г., 14:26
@NP_JavaGeek Если это был ответ, который вы искали, вы должны принять его (как объясненоВот)
 john1638425 сент. 2017 г., 21:01
Существует третья веская причина: подкласс всегда может сделать доступным другой открытый метод, который косвенно предоставляет защищенную функциональность. Поэтому любые попытки запретить его бессмысленны, поэтому Java позволяет вам улучшить видимость.
 Narendra Pathai08 окт. 2012 г., 14:07
Спасибо, Пабло. Тот'Это то, что я искал, действительный аргумент в пользу увеличения видимости.
 Alex30 окт. 2016 г., 17:34
Подумайте о методе клонирования. Этоs защищен, но вы должны сделать его защищенным или публичным

Ваш ответ на вопрос