Почему подкласс в другом пакете не может получить доступ к защищенному методу?
У меня есть два класса в двух разных пакетах:
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();