为什么从外部类访问受保护的成员?

时间:2012-08-28 18:55:57

标签: java inheritance

我正在创建以下类层次结构:

abstract class Shape{
    protected abstract float getArea();
    protected abstract float getVolume();
}

abstract class TwoDimentionalShape extends Shape{
    public abstract float getArea();
    protected float getVolume(){
        return 0;
    }
}

class Square extends TwoDimentionalShape {
    float width, height;
    Square(float w, float h){
        width = w;
        height = h;
    }
    public float getArea(){
        return width*height;
    }
}

public class ShapeTest {
    public static void main(String args[]){
        Shape s = new Square(3, 4);
        System.out.println(s.getVolume());
    }
}

我希望隐藏getVolume()类的TwoDimentionalShape函数,因为它将用于ThreeDimentionalShape类。

问题是我已将该函数声明为受保护,但是当我从main()调用它时,该程序正在运行。为什么会这样?

5 个答案:

答案 0 :(得分:4)

受保护在包中的子类中以及同一包中的类之外可见。看起来您的类都在同一个包中。这就是你能看到它的原因。

一般来说,层次结构是:

公开 - 在所有包和子类中都可用

受保护 - avaialbe在子类和相同的包中

(默认即没有)在同一个包中可用

私人 - 在同一个班级中可用

可以访问(使用反射)一些您通常无法“看到”的字段/方法,尽管这不能保证并且取决于使用的安全管理器。

我认为这个问题的第一个答案很好地解释了这一点 In Java, difference between default, public, protected, and private

答案 1 :(得分:2)

受保护的成员和方法可以在包和inheratance层次结构中进行访问。由于二维没有体积,因此您应该删除该方法。

为3个或更多维度添加getVolume()方法。

getVolume()中添加Shape方法相当于在getDesignation()类中添加Person方法,其中getDesignation()应位于Employee类中延伸Person

答案 2 :(得分:1)

Protected members可由accessedlaw of inheritance之外的包含受保护成员的类的子类组成。Square。 ...

getVolume()类继承了超类 TwoDimentionalShape

中的Square方法

如果 TwoDimentionalShape同一个包 >未扩展 getVolume()类,然后对于该类,方法getVolume()将不可见...我的意思是{{1}}方法将像私有成员一样,它看不到。

答案 3 :(得分:0)

  

我想要做的是为TwoDimentionalShape类隐藏函数getVolume(),因为它将用于ThreeDimentionalShape类。

不是正确的方法。通常,超类声明/定义所有子类共有的方法。如果任何方法不应出现在子类中,那么它应该是超类的私有。如果方法对于某些子类是通用的,但在其他子类中有意义,那么它可能不属于那里,应该在继承继承的某个地方声明/定义。

并非所有Shape都有音量。

protected abstract float getVolume();

不适合Shape。最好将其从Shape中删除,然后将其声明为代表ThreeDimentionalShape可以拥有音量的那个(例如Shape)。

答案 4 :(得分:0)

你应该改变你的类树,不要在Shape类中包含方法定义,因为不是每个形状都有一个卷(甚至可能)

public interface class Shape{ //optional but helpful: interface instead of abstract class. not an abstract class but an interface
    public float getArea();  //not abstract, not protected
    //protected abstract float getVolume(); this should not go in here
}

abstract class TwoDimentionalShape implements Shape{ //implement instead of extend. also this can qualify as an interface instead of an abstract class
    public abstract float getArea();
}

class Square extends TwoDimentionalShape {
    float width, height;
    Square(float w, float h){
        width = w;
        height = h;
    }
    /*public float getArea(){  not needed in a twodimensionalshape
        return width*height;
    }*/
}

public class ShapeTest {
    public static void main(String args[]){
        Shape s = new Square(3, 4);
        System.out.println(s.getVolume()); //will not compile
    }
}

现在您可以创建一个3D类:

abstract class ThreeDimentionalShape implements Shape{
    public abstract float getArea();
    public abstract float getVolume();  //All 3D shapes will have a volume!!
}

class Sphere extends ThreeDimentionalShape {
    float radius;
    Sphere (float radius){

    }
    public float getArea(){  not needed in a twodimensionalshape
        return {place some forgotten formula here};
    }
    public float getVolume(){  not needed in a twodimensionalshape
        return {place some forgotten formula here};
    }
}