Видимость закрытого элемента пакета в сложных комбинациях наследование / пакет - общее правило 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 и все классы могут быть в одном и том же / разных пакетах. Как быстро проверить доступность?

Например, для защищенного члена (базового класса) правило "быстрого угадывания" очень простое:

  1. если Base и Driver находятся в одном пакете (то есть из любого метода Driver, код Base obj = new Base(); obj.baseProtectedMember();компилируется) => любая комбинация будет работать (Base obj1 = new Derived2(); Derived2 obj2 = new Derived2() и т. д. - obj1.baseProtectedMember()а также obj2.baseProtectedMember() видны и могут быть вызваны). И нам все равно, в каких пакетах находятся другие классы!
  2. если 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(),

Другие вопросы по тегам