在之前您的数据成员都预设为"private"成员,也就是私用成员,私用成员只能在类别对象中使用,不能直接透过对象来呼叫使用,而即使是扩充了该类别的衍生类别也是如此,您只能透过该类别所提供的"public"方法成员来呼叫或设定私用成员。
然而有些时候,您希望扩充了基底类别的衍生类别,能够直接存取呼叫基底类别中的成员,但不是透过"public"方法成员,也不是将它宣告为"public",因为您仍不希望这些成员被对象直接呼叫使用。
可以宣告这些成员为「被保护的成员」(protected),保护的意思表示存取它有条件限制以保护该成员,当您将类别成员宣告为受保护的成员之后,继承它的类别就可以直接使用这些成员,但这些成员仍然受到对象范围的保护,不可被对象直接呼叫使用。
要宣告一个成员成为受保护的成员,就使用"protected"关键词,下面这个程序是个实际的例子,您将数据成员宣告为受保护的成员,扩充它的类别就可以直接使用,而不用透过"public"方法成员来呼叫:
public class Rectangle { // 受保护的member protected int x, y; protected int width, height; public Rectangle() { x = y = 0; width = height = 0; } public Rectangle(int x, int y, int width, int height) { this.x = x;?this.y = y; this.width = width;?this.height = height; } public int getX() { return x; } public int getY() { return y; } public int getWidth() { return width; } public int getHeight() { return height; } public int getArea() { return width*height; } }
public class Cubic extends Rectangle { protected int z; protected int length; public Cubic() { z = 0;?length = 0; } public Cubic(int x, int y, int z, int length, int width, int height) { super(x, y, width, height); this.z = z; this.length = length; } public int getLength() { return length; } public int getVolumn() { return length*width*height; } } f
public class UseProtected { public static void main(String[] args) { Cubic c1 = new Cubic(0, 0, 0, 10, 20, 30); System.out.println("c1 volumn: " + c1.getVolumn()); } }
执行结果:
c1 volumn: 6000
在这个例子中,您可以看到直接使用继承下来的受保护成员确实比较方便,方法成员也可以宣告为受保护的成员,对象通常是仅适用于 类别中使用的一些内部处理方法,这些方法对类别外部来说,可能是呼叫它并没有意义或是有危险性,但您在衍生类别中仍可能使用到这些方法,所以通常会将之 宣告为受保护的成员。
一个例子就是在窗口事件处理时,设定事件发生时的呼叫函式,它可以被继承,以自订一些窗口组件,这些方法在事件发生时才会被呼叫,您在类 别外直接呼叫这些方法并没有意义,甚至某些条件没有成立就呼叫它,对整个程序的执行会造成错误,这些方法成员通常就会宣告为受保护的成员。
在设计上有一个考虑,就是对对象内部的field成员最好不要直接呼叫,而仍然透过方法呼叫,例如下面的方式有时不被鼓励:
public class SomeClass { private int someInt; ..... public void someMethod() { int i = someInt; ..... someInt = 1234; .... } }
直接在someMethod()中使用field成员,有时会使得someMethod()失去一些弹性,有时建议使用这样的方式:
public class SomeClass { private int someInt; ..... private int getSomeInt() { return someInt; } private void setSomeInt(int someInt) { this.someInt = someInt; } public void someMethod() { int i = getSomeInt(); ..... setSomeInt(1234); .... } }
这样作的好处是,您可以在存取field成员前作一些额外的处理(这些处理可能原先您要在someMethod()中进行),当然何时要使用,以及 setter、getter要宣告为"public
、"protected"或是"private",则视您的程序需求而定了。
事实上,对于同一个 套件(package) 下的类别,可以直接呼叫彼此的protected成员,而对于不同套件(package)下的成员,不能呼叫彼此的protected成员。
如果在定义成员时没有设定任何的存取修饰,则为预设(default)的存取权限,预设存取权限可以在同一个套件(package)中的其它类别直接存取,但在子类别中不能被直接存取。