Java: Почему метод базового класса может вызывать несуществующий метод? - PullRequest
2 голосов
/ 23 декабря 2009
class BaseClass {
    private void f() {
        System.out.println("Baseclass f()");
    }

    public static void main(String[] args) {
        BaseClass dc = new DerivedClass();
        dc.f();
    }
}

class DerivedClass extends BaseClass {
    public void f() {
        System.out.println("DerivedClass f()");
    }
}

По моему мнению, объект, на который ссылается dc, должен иметь только один не переопределенный метод - public void f (), который делает его (открытый метод) невидимым при обращении к нему со ссылкой на BaseClass. Поскольку объект, на который ссылается dc, также не имеет закрытого метода void f (), поскольку DeriverClass не может наследовать закрытый метод, как объект dc может ссылаться на вызов метода f ()?

спасибо.

Ответы [ 4 ]

4 голосов
/ 23 декабря 2009

Распространенным заблуждением (ish) является то, что private - это экземпляр, а не класс.

Например:

class Foo
{
    private int a;

    public bar(final Foo other)
    {
        other.a = 5;
    }
}

У некоторых людей сложилось впечатление, что приведенный выше код не должен работать, потому что «а» является «частным». Это не так, любой экземпляр Foo может получить доступ к закрытым переменным / методам любого другого экземпляра Foo. «private» означает, что экземпляры других классов (в данном случае, кроме Foo) не могут получить доступ к закрытым членам.

3 голосов
/ 23 декабря 2009

Для простоты DerivedClass (DC) наследует private void f() от BaseClass (BC). Этот унаследованный метод недоступен для DC, но он существует, потому что любой метод, вызываемый в части BC, должен иметь доступ ко всем BC. Поэтому, когда вы приводите DC к BC, унаследованный метод становится доступным. Теперь, когда вы запускаете код внутри класса BC, он может получить доступ ко всем закрытым членам BC. Если вы переместили основной на DC, он не должен компилироваться, не говоря уже о запуске.

1 голос
/ 23 декабря 2009

Четыре пункта:

(1) Чтобы уточнить, что написал vivyzer, код компилируется, потому что основной метод в BaseClass имеет доступ к собственным закрытым методам класса.Если вы написали код как:

class BaseClass {
  private void f() { }
}

class DerivedClass {
  public void f() { }
}

class Bystander {
  public static void main() {
    BaseClass inst = new DerivedClass();
    inst.f();
  }
}

, тогда код не будет компилироваться.

(2) Это разрешено языком для поддержки сценария использования, когда автор базового класса можетдобавьте новый приватный метод, не беспокоясь о производных типах других авторов.

(3) Вы не увидите этого, если метод не был приватным.Если бы базовый класс f () имел пакет или защищенную видимость, то этот метод был бы виртуальным методом.

(4) Java не поддерживает обратную сторону пункта # 2.В частности, если у производного класса есть закрытый метод, а новая версия базового типа вводит не приватный метод с той же сигнатурой, производный класс и новый базовый класс нельзя использовать вместе.Существуют и другие языки (например, C #), которые более полно решают эти виды модульных вопросов разработки поколений.Если вас интересует этот аспект, прочитайте Artima: Управление версиями, Виртуальный и Переопределение

1 голос
/ 23 декабря 2009

Основной метод находится внутри BaseClass, и частные методы видны ему. Если main находится в каком-то другом классе, он не скомпилируется.

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