Наследование Java - пожалуйста, объясните - PullRequest
3 голосов
/ 15 ноября 2009
class A {
    public void talk(){
        this.sayIt();
    }

    private void sayIt(){
        System.out.println("class A says...");
    }
}

class B extends A {
    private void sayIt(){
        System.out.println("class B says...");
    }
}

Тестовый класс, основной метод:

B b = new B();
b.talk() 

//output
class A says...

Я не могу получить это, так как:

Класс B наследуется от класса A , открытого члена, и не может видеть / наследовать закрытую функцию. Так что в классе B мы могли бы позвонить talk () . // поскольку он наследуется родительским классом.

Теперь в методе talk () вызывается sayIt () , поскольку sayIt () определено в классе B

Я ожидал бы, что вызов B.sayIt () будет выполнен при выполнении this.sayIt () .

Разве «это» не относится к классу B ?

Пожалуйста, объясните.

Ответы [ 10 ]

6 голосов
/ 15 ноября 2009

Поскольку вы определили sayIt () как закрытый, класс B не может его переопределить. Таким образом, у вас есть два определения sayIt (), а не одно, которое переопределяется подклассом.

Находясь внутри раздела кода класса A, он всегда будет вызывать версию из класса A, даже если версия класса B была защищенной или общедоступной. Это связано с тем, что класс A знает только о версии из класса A, поскольку версия класса B является , а не переопределением, а совершенно другим методом, который просто имеет одно и то же имя.

Находясь внутри раздела кода класса B, он всегда будет вызывать версию из класса B, поскольку версия класса A помечена как закрытая. Как отметили другие, если вы измените определение на защищенное или общедоступное, оно будет видно классу B и будет делать то, что вы хотите.

Обратите внимание, что если бы вы использовали видимость по умолчанию (пакет), правила области видимости стали бы очень сложными, и фактические результаты варьировались бы в зависимости от того, какие подклассы находятся в одном пакете, а какие - в разных.

3 голосов
/ 15 ноября 2009

Попробуйте сделать protected вместо private на sayIt. sayIt на B не переопределяет sayIt на A.

2 голосов
/ 15 ноября 2009

Вы пытаетесь переопределить приватные методы. Это не имеет смысла.

0 голосов
/ 15 ноября 2009

Немного отклонился от темы, но может помочь вам лучше понять наследование Java.

http://webmoli.com/2008/08/02/why-multiple-inheritance-is-not-allowed-in-java/

0 голосов
/ 15 ноября 2009

В соответствии со спецификацией языка Java 8.4.8:

A class C inherits from its direct superclass and direct superinterfaces
all non-private methods (whether abstract or not) of the superclass and
superinterfaces that are public, protected or declared with default access
in the same package as C and are neither overridden nor hidden by a
declaration in the class.

Таким образом, B не наследовал A.sayIt () и, следовательно, не переопределял его.

0 голосов
/ 15 ноября 2009

Поскольку в talk вы ссылаетесь на this.sayIt, а объект B является экземпляром A.

Объект A не знает методов в B. Сделайте объект A абстрактным классом с sayIt абстрактным методом, который вы вызываете в разговоре A, или измените видимость sayIt.

Также - используйте аннотации, и IDE уведомит вас предупреждениями.

0 голосов
/ 15 ноября 2009

Поскольку sayIt является частным методом, он фактически не переопределяется. Один из способов помочь понять это - добавить аннотацию @Override к любому методу, который, по вашему мнению, переопределяет что-то из суперкласса. Если вы не правы (как в этом случае), то компилятор скажет вам.

0 голосов
/ 15 ноября 2009

"Разве" это "не относится к классу B?" - Нет. Хотя вы создаете экземпляр из класса B, вы все равно ссылаетесь на метод базового типа - talk (). Одним из способов достижения этой же цели является шаблон-метод.

/ BB

0 голосов
/ 15 ноября 2009

Да, «this» из b.talkIt() относится к классу B, но поскольку sayIt() является частным в A, а talkIt() декальдируется в A и не переопределяется в B, sayIt() будет ссылаться на тот в A.

Вы можете посмотреть на это так. sayIt() из A является частным, поэтому его нельзя переопределить. Поскольку он не переопределен, вызов sayIt() методами A всегда будет указывать на тот, который известен A (поскольку он не переопределен).

Надеюсь, это поможет.

0 голосов
/ 15 ноября 2009

Если вы измените защищенный метод sayIt, он будет работать так, как вы ожидаете.

Кажется, вы немного озадачены тем, как это работает с переопределенными методами. Если я не ошибаюсь, то, что вы пытаетесь сделать, совершенно нормально в C ++, но не в Java.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...