可以访问一个受保护变量,而另一个不受访问。为什么?

问题描述 投票:2回答:1

这是一个受保护的继承问题。我确实理解受保护意味着在一个包中,它就像是公开的一样。在包之外,一般来说,只有在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;访问?

java inheritance protected
1个回答
2
投票
 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

© www.soinside.com 2019 - 2024. All rights reserved.