为什么不能从子类访问受保护的方法?
Why protected method is not accessible from subclass?
考虑以下代码片段:
package vehicle;
public abstract class AbstractVehicle {
protected int speedFactor() {
return 5;
}
}
package car;
import vehicle.AbstractVehicle;
public class SedanCar extends AbstractVehicle {
public static void main(String[] args) {
SedanCar sedan = new SedanCar();
sedan
.speedFactor();
AbstractVehicle vehicle = new SedanCar();
// vehicle //WON'T compile
// .speedFactor();
}
}
SedanCar
是 AbstractVehicle
的子 class,其中包含 protected
方法 speedFactor
。如果方法 speedFactor
被同一个 class 引用,我可以调用它。当 super class 用于引用时,方法 speedFactor
不可访问。
隐藏方法的原因是什么?
因为 protected
对 class 本身(如私有)及其子 class 实例可见。它不是 public。
例如,
package vehicles;
public abstract class AbstractVehicle {
protected int speedFactor() {
return 5;
}
public int getSpeed() {
return 10*speedFactor(); //accessing speedFactor() "privately"
}
}
package vehicles.cars;
public class SedanCar extends AbstractVehicle {
@Override
protected int speedFactor() { //overriding protected method (just to show that you can do that)
return 10;
}
@Override
public int getSpeed() {
return 20*speedFactor(); //this is part of the instance (!!!) therefore it can access speedFactor() protected method too
}
}
package vehicles.main;
public class Main {
public static void main(String[] args) {
AbstractVehicle vehicle = new SedanCar();
int speed = vehicle.getSpeed(); //accessing public method
vehicle.speedFactor(); //cannot access protected method from outside class (in another package)
}
}
静态 main()
方法不是实例的一部分,这就是它无法访问受保护方法的原因。
protected 修饰符指定该成员只能在其自己的包内访问(与 package-private 一样),此外,它的 class 在另一个包中的子class .
这就是为什么不能直接调用vehicle对象的main方法里面的方法的原因。
参见:https://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html
您的 SedanCar
class 与 AbstractVehicle
class 在不同的包中。 protected
方法只能从 相同的包 或子 class 中访问。
在SedanCar
的情况下:
SedanCar sedan = new SedanCar();
sedan.speedFactor();
您正在从同一个包中调用 protected
方法:好的。 SedanCar
在包 car
中,main()
方法在包 car
中的 class 中(实际上是相同的 class)。
在AbstractVehicle
的情况下:
AbstractVehicle vehicle = new SedanCar();
vehicle.speedFactor();
您尝试调用 protected
方法,但来自另一个包:不正常。您尝试调用它的 main()
方法在包 car
中,而 AbstractVehicle
在包 vehicle
.
中
基本这样理解:
您有一个 AbstractVehicle
类型的变量,它在另一个包 (vehicle
) 中声明。它可能包含也可能不包含 SedanCar
的动态类型。在你的情况下它确实如此,但它也可以包含在另一个包中定义的任何其他 subclass 的实例,例如在 sportcar
。并且由于您在包 car
中(main()
方法),您不能调用 vehicle.speedFactor()
(这是受保护的 AbstractVehicle.speedFactor()
)。
回到我的 SCJP Java 1.5 天,我曾经记得的一件事是警惕超类引用变量。现在看到这一点并不令人惊讶,而这让人困惑的一件事是规则是受保护的,对子类或同一个包是可见的。如果它既是子类又是不同的包怎么办?
如果您创建另一个包,并执行
package yetAnotherPackage;
import car.SedanCar;
public class Main {
public static void main(String[] args) {
new SedanCar().speedFactor();
}
}
你会看到
The method speedFactor() from the type AbstractVehicle is not visible
看起来规则刚刚传播。只要你有一个子类并尝试访问子类包中的受保护方法(或者如果没有子类,则访问父类包),你应该是好的。
不同包中的 Subclass 无法使用 superclass 引用从 superclass 访问受保护的方法和受保护的变量。
在 subclass 中访问 superclass 的受保护数据的唯一方法是通过继承
下面是两个代码片段
package nee;
import parentdata.Parent;
class Child extends Parent{
public void testIt(){
System.out.println(x); // able to access protected x defined in Parent
}
}
package nee;
import parentdata.Parent;
class Child extends Parent {
public void testIt(){
Parent p=new Parent();
System.out.println(p.x) // results in compile time error
}
}
在语言规范中
6.6.2.1 访问受保护的会员
令 C 为声明受保护成员 m 的 class。只允许在C的subclassS的body内访问。另外,如果Id表示实例字段或实例方法,则:
If the access is by a qualified name Q.Id, where Q is an ExpressionName, then the access is permitted if and only if the type of the expression Q is S or a subclass of S.
If the access is by a field access expression E.Id, where E is a Primary expression, or by a method invocation expression E.Id(. . .), where E is a Primary expression, then the access is permitted if and only if the type of E is S or a subclass of S.
有关详细信息,请访问
http://www.jot.fm/issues/issue_2005_10/article3.pdf
考虑以下代码片段:
package vehicle;
public abstract class AbstractVehicle {
protected int speedFactor() {
return 5;
}
}
package car;
import vehicle.AbstractVehicle;
public class SedanCar extends AbstractVehicle {
public static void main(String[] args) {
SedanCar sedan = new SedanCar();
sedan
.speedFactor();
AbstractVehicle vehicle = new SedanCar();
// vehicle //WON'T compile
// .speedFactor();
}
}
SedanCar
是 AbstractVehicle
的子 class,其中包含 protected
方法 speedFactor
。如果方法 speedFactor
被同一个 class 引用,我可以调用它。当 super class 用于引用时,方法 speedFactor
不可访问。
隐藏方法的原因是什么?
因为 protected
对 class 本身(如私有)及其子 class 实例可见。它不是 public。
例如,
package vehicles;
public abstract class AbstractVehicle {
protected int speedFactor() {
return 5;
}
public int getSpeed() {
return 10*speedFactor(); //accessing speedFactor() "privately"
}
}
package vehicles.cars;
public class SedanCar extends AbstractVehicle {
@Override
protected int speedFactor() { //overriding protected method (just to show that you can do that)
return 10;
}
@Override
public int getSpeed() {
return 20*speedFactor(); //this is part of the instance (!!!) therefore it can access speedFactor() protected method too
}
}
package vehicles.main;
public class Main {
public static void main(String[] args) {
AbstractVehicle vehicle = new SedanCar();
int speed = vehicle.getSpeed(); //accessing public method
vehicle.speedFactor(); //cannot access protected method from outside class (in another package)
}
}
静态 main()
方法不是实例的一部分,这就是它无法访问受保护方法的原因。
protected 修饰符指定该成员只能在其自己的包内访问(与 package-private 一样),此外,它的 class 在另一个包中的子class .
这就是为什么不能直接调用vehicle对象的main方法里面的方法的原因。
参见:https://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html
您的 SedanCar
class 与 AbstractVehicle
class 在不同的包中。 protected
方法只能从 相同的包 或子 class 中访问。
在SedanCar
的情况下:
SedanCar sedan = new SedanCar();
sedan.speedFactor();
您正在从同一个包中调用 protected
方法:好的。 SedanCar
在包 car
中,main()
方法在包 car
中的 class 中(实际上是相同的 class)。
在AbstractVehicle
的情况下:
AbstractVehicle vehicle = new SedanCar();
vehicle.speedFactor();
您尝试调用 protected
方法,但来自另一个包:不正常。您尝试调用它的 main()
方法在包 car
中,而 AbstractVehicle
在包 vehicle
.
基本这样理解:
您有一个 AbstractVehicle
类型的变量,它在另一个包 (vehicle
) 中声明。它可能包含也可能不包含 SedanCar
的动态类型。在你的情况下它确实如此,但它也可以包含在另一个包中定义的任何其他 subclass 的实例,例如在 sportcar
。并且由于您在包 car
中(main()
方法),您不能调用 vehicle.speedFactor()
(这是受保护的 AbstractVehicle.speedFactor()
)。
回到我的 SCJP Java 1.5 天,我曾经记得的一件事是警惕超类引用变量。现在看到这一点并不令人惊讶,而这让人困惑的一件事是规则是受保护的,对子类或同一个包是可见的。如果它既是子类又是不同的包怎么办?
如果您创建另一个包,并执行
package yetAnotherPackage;
import car.SedanCar;
public class Main {
public static void main(String[] args) {
new SedanCar().speedFactor();
}
}
你会看到
The method speedFactor() from the type AbstractVehicle is not visible
看起来规则刚刚传播。只要你有一个子类并尝试访问子类包中的受保护方法(或者如果没有子类,则访问父类包),你应该是好的。
Subclass 无法使用 superclass 引用从 superclass 访问受保护的方法和受保护的变量。 在 subclass 中访问 superclass 的受保护数据的唯一方法是通过继承
下面是两个代码片段
package nee;
import parentdata.Parent;
class Child extends Parent{
public void testIt(){
System.out.println(x); // able to access protected x defined in Parent
}
}
package nee;
import parentdata.Parent;
class Child extends Parent {
public void testIt(){
Parent p=new Parent();
System.out.println(p.x) // results in compile time error
}
}
在语言规范中 6.6.2.1 访问受保护的会员
令 C 为声明受保护成员 m 的 class。只允许在C的subclassS的body内访问。另外,如果Id表示实例字段或实例方法,则:
If the access is by a qualified name Q.Id, where Q is an ExpressionName, then the access is permitted if and only if the type of the expression Q is S or a subclass of S.
If the access is by a field access expression E.Id, where E is a Primary expression, or by a method invocation expression E.Id(. . .), where E is a Primary expression, then the access is permitted if and only if the type of E is S or a subclass of S.
有关详细信息,请访问 http://www.jot.fm/issues/issue_2005_10/article3.pdf