这是一个受保护的继承问题。我确实理解受保护意味着在一个包中,它就像是公开的一样。在包之外,一般来说,只有在INSIDE子类时才能访问它。这不是我的困惑。我的困惑在于正在发生的一点挑剔,我不知道为什么。我将在代码之后解释问题的内容。您将获得包含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
}
}
超类有两个受保护的变量,一个是静态的。另一个包中的子类创建了一个新的超类对象,试图访问这两个变量。为什么你能够通过对象通过它访问静态变量,但不能通过它访问实例变量?他们都受到保护。两者都来自同一个班级。两者都由同一个对象访问。请注意,对于那些认为这可能是重复的人:其他问题只是询问受保护的工作原理,但是他们没有问到具体的问题,为什么只能访问受保护的这两个变量中的一个。
这不是一个如何修复代码的问题。我知道如何让最终游戏发挥作用。问题是为什么它可以通过t.x;
而不是t.y;
访问?
t.x = 1; //compiles
这是一个static
领域。所以你应该把它写成TestA.x
(会有编译器警告)。
静态保护字段可以从子类的静态代码中访问(或者从非静态代码中访问)。
t.y = 2; //field not visible, fails to compile
这是一个实例字段。可以从子类的实例方法中访问受保护的实例字段。但只能从那些方法中。您无法从静态方法中调用它们(即使该静态方法恰好位于子类上)。
如果需要从另一个类中的静态方法访问字段,则需要将该字段设置为public或将需要它的代码移动到同一个包中。
但只能从那些方法中。
并且只有当您可以确定所讨论的实例实际上来自您自己的类时。
在你的例子中
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
。