Видимость закрытого элемента пакета в сложных комбинациях наследование / пакет - общее правило Qiuck для проверки видимости - PullRequest
0 голосов
/ 05 января 2019

Если базовый и производный классы находятся в разных пакетах, то закрытый для пакета член из 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 и каждый класс (ы) может быть в одном и том же / разных пакетах. Как быстро проверить доступность?

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

  1. , если База и драйвер находятся в одном пакете (то есть от любого драйвера метод код Base obj = new Base(); obj.baseProtectedMember(); компилируется) => любая комбинация будет работать (Base obj1 = new Derived2 (); Derived2 obj2 = новый Derived2 () и т. Д. - obj1.baseProtectedMember() и obj2.baseProtectedMember() видны и могут быть вызваны). И нам все равно, в каких пакетах другие классы!
  2. , если база и драйвер НЕ находятся в одном пакете (то есть от любого драйвера метод код Base obj = new Base(); obj.baseProtectedMember(); НЕ компилируется) => любая комбинация (см. 1) НЕ будет работать. И нам все равно, в каких пакетах другие классы!

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

P.S. Интересное примечание:

Если я переопределю методы в Derived и DerivedFromDerived (оставив их закрытыми для пакета) в приведенном выше фрагменте кода (вверху сообщения), вывод будет:

f() from Base called
f() from Base called

1 Ответ

0 голосов
/ 06 января 2019

Base и Driver находятся в одном пакете, поэтому Driver может видеть приватные методы пакета Base. Если вы объявите Base obj1 = new Derived() как Derived obj1 = new Derived(), вы не увидите f(). То же самое верно для Base obj2 = new DerivedFromDerived(), в том случае, если вы объявите его как DerivedFromDerived, вы не увидите f().

...