Почему подкласс в другом пакете не может получить доступ к защищенному методу?

У меня есть два класса в двух разных пакетах:

package package1;

public class Class1 {
    public void tryMePublic() {
    }

    protected void tryMeProtected() {
    }
}


package package2;

import package1.Class1;

public class Class2 extends Class1 {
    doNow() {
        Class1 c = new Class1();
        c.tryMeProtected(); // ERROR: tryMeProtected() has protected access in Class1
        tryMeProtected();  // No error
    }    
}

Я могу понять, почему нет ошибки при вызове tryMeProtected(), так как Class2 видит этот метод, поскольку он наследует от Class1.

Но почему объект Class2 не может получить доступ к этому методу на объекте Class1 с помощью c.tryMeProtected();?

Ответ 1

Защищенные методы могут быть доступны через наследование в подклассах вне пакета. И, следовательно, работает второй подход tryMeProtected();.

Код ниже не компилируется, потому что мы не вызываем унаследованную версию защищенного метода.

 Class1 c = new Class1();
 c.tryMeProtected(); // ERROR: tryMeProtected() has protected access in Class1

Следуйте этой ссылке fooobar.com/questions/491315/..., чтобы узнать больше.

Ответ 2

Я считаю, что вы неправильно понимаете разницу между видимостью package и protected.

package 1;

public class MyClass1 {
    public void tryMePublic() { System.out.println("I'm public"); }
    protected void tryMeProtected() { System.out.println("I'm protected"); }
    void tryMePackage() { System.out.println("I'm package"); }
}
  • tryMePublic будет доступен везде, где вы находитесь.
  • tryMeProtected будет доступен для каждого подкласса И каждого класса в одном пакете.
  • tryMePackage будет доступен для каждого класса в одном пакете (недоступен в классе children, если есть в другом пакете)

класс детей в одном пакете

package package1;

public class Class2 extends MyClass1 {
    public void doNow() {
        tryMePublic(); // OK
        tryMeProtected(); // OK
        tryMePackage(); // OK
    }    
}

Класс детей в другой упаковке

package package2;

import package1.MyClass1;

public class Class3 extends MyClass1 {
    public void doNow() {
        MyClass1 c = new MyClass1();
        c.tryMeProtected() // ERROR, because only public methods are allowed to be called on class instance, whereever you are
        tryMePublic(); // OK
        tryMeProtected(); // OK
        tryMePackage(); // ERROR
    }    
}

Ответ 3

Вы используете два разных пакета, и вы не получаете доступа к родительским атрибутам прямым наследованием, а промежуточным родительским экземпляром, объявленным в дочернем классе (аналогично композиции). = > , что работает не путь protected.

Только прямое наследование позволяет доступным защищенным родительским атрибутам.

Таким образом, вы можете сделать это:

public class Class2 extends Class1 {
    doNow() {
        tryMeProtected();  // No error since direct inheritance 
    }    
}

но никогда этого:

public class Class2 extends Class1 {
    doNow() {
        Class1 c = new Class1();
        c.tryMeProtected(); // this is not a direct inheritance! since `c`, although a parent one is an intermediate instance created in the child instance. => bad
    }    
}

В самом деле, это особенность ключевого слова protected, которое часто неправильно понимается.

Ответ 4

В соответствии с методами определения модификатора защищенного доступа Java, которые объявлены защищенными в суперклассе, могут быть доступны только подклассы другого пакета или любого класса в пакете класса защищенных членов.

вы не можете получить доступ к защищенному методу, создав объект класса. Поэтому для доступа к защищенному методу вы должны расширить суперкласс (это объясняет ваш второй звонок правильно)

Ответ 5

Это может быть достигнуто двумя способами.

1. Либо создав объект класса Child, а затем получив доступ к защищенному методу родительского класса.

ПАКЕТ 1

public class Class1 {
    protected void m1() {
        System.out.println("m1 called");
    }
}

упаковке2

public class Class2 extends Class1 {

    public static void main(String[] args) {
        Class2 class2 = new Class2();
        class2.m1();
    }
}

2. Или путем прямого вызова метода из класса Child

eg tryMeProtected();