这是一个受保护的继承问题。我确实了解到,protected意味着在软件包中,就好像它是公共的。通常,在包外部,只有在子类内部时才可以访问它。那不是我的困惑。我的困惑是正在发生一些小问题,我不知道为什么。在代码之后,我将解释问题的实质。为您提供了包含TestA类的包com.wobble.foo和包含扩展classA的TestB类的com.wobble.bar。
//A Package
package com.wobble.foo;
public class TestA{
static protected int x = 5;
protected int y = 6;
}
//A different Package
package com.wobble.bar;
public class TestB extends TestA{
static{
TestA t = new TestA();
t.x = 1; //compiles
t.y = 2; //field not visible, fails to compile
}
}
超类有两个受保护的变量,一个是静态的。不同包中的子类创建了一个新的超类对象,试图访问这两个变量。为什么通过对象可以通过它访问静态变量,而不能通过它访问实例变量呢?它们都受到保护。两者来自同一班级。两者都由同一个对象访问。请注意,对于那些认为这可能是重复的人:其他问题只是询问受保护的工作方式,而他们却没有提出具体问题,为什么只能访问这两个受保护变量中的一个。
-谢谢
PS:
这不是一个如何解决代码的问题。我知道如何使最终游戏正常运行。问题是为什么可以通过t.x;
而不是t.y;
来访问它?
答案 0 :(得分:2)
t.x = 1; //compiles
这是一个static
字段。因此,您应该将其编写为TestA.x
(会有关于此的编译器警告)。
可以从子类的静态代码(或与此相关的非静态代码)访问静态保护字段。
t.y = 2; //field not visible, fails to compile
这是一个实例字段。可从子类的实例方法内访问受保护的实例字段。但只能从这些方法中进行。您不能从静态方法调用它们(即使该静态方法恰好在子类上)。
如果您需要从另一个类的静态方法访问这些字段,则需要将该字段公开或将需要它的代码移到同一包中。
但只能从这些方法中进行。
并且仅在您可以确定所讨论的实例实际上来自您自己的类时,才可以。
在您的示例中
TestA t = new TestA();
t.y = 2;
t.y
不可见,因为TestB
中的代码无法访问TestA
上实例上的受保护字段。 It needs to be an instance of TestB
。不过,相同的代码也可以在TestA
上的方法内部工作。
以下内容也不起作用:
// in TestB
void boo(TestA someInstance){
this.y = someInstance.y;
// does not compile, because someInstance.y is not visible
// because it could be from unknown TestC
}
好吧,但是那我怎样才能访问t.x?它也是受保护的成员,我仍然不是。
这里完全不使用实例t
(它could even be null
仍然可以使用)。静态方法仅在变量的编译时(声明的)类型上分派。理想情况下,t.x
should not even be allowed,但至少会收到编译器警告。
它是静态的,因此从技术上讲,您不是通过父类来访问它,而是通过子类来访问它?即t.x-> x-> TestB.x是通过TestB获取的?
静态方法不能被子类覆盖。 TestB.x
只是一种写TestA.x
的令人困惑(或方便,取决于您的外观)的方式。您可以将其视为自动从父类导入所有(公共和受保护)静态字段和变量的子类。可以减少击键次数,但不会改变行为(某些方法与实例方法的工作方式非常不同,后者是根据实际实例类型动态分配的)。
无论哪种方式,由于TestA.x
受保护,因此TestA
的子类(包括TestB
)中的静态代码块可以访问它。