Если базовый и производный классы находятся в разных пакетах, то закрытый для пакета член из Base не должен наследоваться и, следовательно, он должен отсутствовать в Derived , то есть такой член должен быть недоступен как через Base obj = new Derived()
, так и Derived obj = new Derived()
- obj.member()
должны выдавать ошибку компиляции в любом случае!
Но я вижу, что для Base obj = new Derived()
, obj.f()
доступен!
Да, приватные члены все еще там, потому что когда я создаю new Derived()
, тогда new Base()
также создается со всеми его приватными членами (под капотом). Но если я изменю package-private f()
в приведенном ниже коде на private , obj.f()
будет ошибка компиляции для Base obj = new Derived()
, как и ожидалось ... В любом случае, Я подозреваю, что в моем примере с закрытыми членами пакета, это в точности так: доступ из класса Derived к (неявно существующим) закрытым (-) членам его суперкласса (базового класса).
(-) (потому что Base и Derived находятся в разных пакетах)
package com.main_pkg;
public class Base {
void f() { } // default visibility
}
и
package org.another_pkg;
import com.main_pkg.Base;
public class Derived extends Base {
}
и
package com.totally.different_pkg;
import org.another_pkg.Derived;
public class DerivedFromDerived extends Derived {
}
наконец
import org.another_pkg.Derived;
import com.totally.different_pkg.DerivedFromDerived;
public class Driver { // Base class is in same pkg as Driver!
public static void main(String[] args) {
Base obj1 = new Derived();
obj1.f(); // f() is visible!
Base obj2 = new DerivedFromDerived();
obj2.f(); // f() is visible!
}
}
Не могли бы вы сформулировать быстрое и простое практическое правило (другими словами, чем в JLS и общих определениях видимости по умолчанию), как понять видимость (доступ) в сложном наследовании / пакет комбинаций (у нас может быть сложная иерархия Base-> Derived-> Derived2-> Derived3 и каждый класс (ы) может быть в одном и том же / разных пакетах. Как быстро проверить доступность?
Например, для защищенного члена (базового класса) правило "быстрого угадывания" очень простое:
- , если База и драйвер находятся в одном пакете (то есть от любого драйвера
метод код
Base obj = new Base(); obj.baseProtectedMember();
компилируется) => любая комбинация будет работать (Base obj1 = new Derived2 ();
Derived2 obj2 = новый Derived2 () и т. Д. - obj1.baseProtectedMember()
и obj2.baseProtectedMember()
видны и могут быть вызваны). И нам все равно, в каких пакетах другие классы!
- , если база и драйвер НЕ находятся в одном пакете (то есть от любого драйвера
метод код
Base obj = new Base(); obj.baseProtectedMember();
НЕ компилируется) => любая комбинация (см. 1) НЕ будет работать. И нам все равно, в каких пакетах другие классы!
Но для закрытых для пакета членов нас волнует, в каком пакете какой класс иерархии равен , и я не могу сформулировать простое и надежное правило "быстрого угадывания" для общего случая ...
P.S. Интересное примечание:
Если я переопределю методы в Derived и DerivedFromDerived (оставив их закрытыми для пакета) в приведенном выше фрагменте кода (вверху сообщения), вывод будет:
f() from Base called
f() from Base called