Почему java не позволяет сделать метод экземпляра родительского класса более строгим в дочернем классе - PullRequest
2 голосов
/ 11 октября 2010

Полиморфизм позволяет программисту наследовать, переопределять или перегружать метод экземпляра родительского класса.

Но это не позволит сделать метод экземпляра родительского класса более строгим в дочернем классе.то есть он не позволяет использовать то же имя метода экземпляра родительского класса, чтобы объявить его как private в дочернем классе.

Также JVM идентифицирует версию родительского класса метода экземпляра, если дочерний класс не переопределил его.

Точно так же, почему JVM не определяет версию родительского класса метода экземпляра, если дочерний класс делает его более ограничительным?

Можно рассмотреть более ограничительный метод родительского класса в дочернем классе.как специфичный для дочернего класса метод вместо переопределенного метода компилятором.

Ответы [ 5 ]

17 голосов
/ 11 октября 2010

Все это делается для того, чтобы следовать принципу подстановки Лискова .

Чтобы наследование в объектно-ориентированном программировании работало должным образом, дочерний класс должен быть в состоянии заменитьдля экземпляра родительского класса и не нарушать пользователя класса.

Создание дочернего метода более ограничительным в основном говорит: «Я не хочу, чтобы этот метод был видимым».Наличие в этом случае JVM, автоматически заменяющей реализацию родительского класса, просто добавит огромную путаницу - просто изменение поведения вызова может вызвать очень неожиданное поведение, даже полностью внутри дочернего класса ...

2 голосов
/ 11 октября 2010

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

class A {
    public void methodA(){
    }
}
class B extends A {
    @Override
    private void methodA(){
    }
}
//
public static void main(String... args){
    A a = new B();
    a.methodA(); // Should call the overridden method but as it's private it can't work.
}

Вы предоставили решение для этого случая, но оно также имеет недостаток:

class A {
    public void methodA(){
    }

    public void methodB(){
        methodA();
    }
}
class B extends A {
    @Override
    protected void methodA(){
    }
}
//
public static void main(String... args){
    A a = new B();
    a.methodB(); // Will methodA from A be called or from B ?
}

Там решение сложное и противоречит философии Java.Это более или менее, почему используется текущее решение;более простой, даже если определенная функция не может быть использована.

2 голосов
/ 11 октября 2010

Более строгий метод родительского класса в дочернем классе можно рассматривать как метод, специфичный для дочернего класса

Авторы Java могли бы реализовать это.И многое другое, например печально известное множественное наследование.Но это сделает язык более сложным и принесет очень мало пользы.

Если вам нужна закрытая версия метода родителя, почему бы вам просто не дать ему другое имя?Поскольку он будет вызываться только из вашего дочернего класса, разницы не будет.

0 голосов
/ 12 октября 2010

То, что вы хотите сделать, это обернуть «родительский» класс в другой, используя композицию, а не наследование, когда вы хотите ограничить доступ.

Таким образом, вы создаете новый класс, имеющий класс, который вы хотите обернуть в качестве члена, и предоставляете доступ к тому, что вы хотите, создав собственный API. Конечно, вы не можете использовать новый класс вместо старого, но это не имеет никакого смысла. Если вы этого не хотите, я согласен на 100% с ответом Рида Копси (я согласен на 100%, даже если это то, что вы хотели сделать).

0 голосов
/ 11 октября 2010

Если я вас правильно понимаю, вы говорите, что я должен иметь возможность написать:

public class Foo
{
  public int bar()
  {
    return 1;
  }
}
public class Foo2 extends Foo
{
  private int bar()
  {
    return 2;
  }
  public int barBar()
  {
    return bar();
  }
}
public static void main(String[] args())
{
  Foo2 foo2=new Foo2();
  System.out.println(foo2.bar());
  System.out.println(foo2.barBar());
}

Тогда, если я создам экземпляр класса Foo2 и вызов bar из класса, он должен вызватьFoo2.bar, поэтому я должен вернуться к 2, но если я вызову bar из-за пределов класса, он должен вызвать Foo.bar, чтобы я вернулся 1.

То есть, результат вышеприведенной программы должен быть:1 2

Ну, так как это вопрос о дизайне языка, я думаю, простой ответ: «Потому что именно так дизайнеры Java решили это сделать».

реальный вопрос в том, почему вы хотите, чтобы он вел себя так, как вы описали?У вас есть приложение, где это было бы полезно?Мне кажется, что это просто сбивает с толку.

...