Видимость закрытого элемента пакета в сложных комбинациях наследование / пакет - общее правило Qiuck для проверки видимости
Если классы Base и Derived находятся в разных пакетах, то закрытый для пакета член из Base не должен наследоваться и, следовательно, он должен отсутствовать в Derived, то есть такой член должен быть недоступен как до Base obj = new Derived()
а также Derived obj = new Derived()
-obj.member()
должен дать ошибку компиляции в любом случае!
Но я вижу это для Base obj = new Derived()
, obj.f()
доступно!
Да, частные члены все еще там, потому что, когда я создаю new Derived()
затем new Base()
также создается со всеми его частными членами (под капотом). Но если я поменяю пакет-приват f()
в коде ниже для частного, 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 и Driver находятся в одном пакете (то есть из любого метода Driver, код
Base obj = new Base(); obj.baseProtectedMember();
компилируется) => любая комбинация будет работать (Base obj1 = new Derived2(); Derived2 obj2 = new Derived2() и т. д. -obj1.baseProtectedMember()
а такжеobj2.baseProtectedMember()
видны и могут быть вызваны). И нам все равно, в каких пакетах находятся другие классы! - если Base и Driver НЕ находятся в одном пакете (то есть из любого метода Driver, код
Base obj = new Base(); obj.baseProtectedMember();
НЕ компилируется) => любая комбинация (см. 1) НЕ будет работать. И нам все равно, в каких пакетах находятся другие классы!
Но для закрытых членов пакета нас интересует, в каком пакете находится класс иерархии, и я не могу сформулировать простое и надежное правило "быстрого угадывания" для общего случая...
PS Интересная СТОРОНА-ПРИМЕЧАНИЕ:
Если я переопределю методы в Derived и DerivedFromDerived (оставив их закрытыми для пакета) в приведенном выше фрагменте кода (вверху сообщения), вывод будет таким:
f() from Base called
f() from Base called
1 ответ
Base
а также Driver
находятся в одной упаковке, поэтому Driver
можно увидеть Base
Пакетные частные методы. Если вы объявили Base obj1 = new Derived()
как Derived obj1 = new Derived()
ты не увидишь f()
, То же самое относится и к Base obj2 = new DerivedFromDerived()
в том, что если вы объявили это как DerivedFromDerived
не увидишь f()
,