大可制作:QQ群:31564239(asp|jsp|php|mysql)

Java Gossip: 被保护的(protected)成员

在之前您的数据成员都默认为"private"成员,也就是私用成员,私用成员只能在类对象中使用,不能直接透过对象来调用使用,而即使是继承了该类的衍生类也是如此,您只能透过该类所提供的"public"方法成员来调用或设定私用成员。

然而有些时候,您希望继承了基底类的衍生类,能够直接存取调用基底类中的成员,但不是透过"public"方法成员,也不是将它声明为"public",因为您仍不希望这些成员被对象直接调用使用。

可以声明这些成员为“被保护的成员”(protected),保护的意思表示存取它有条件限制以保护该成员,当您将类成员声明为受保护的成员之后,继承它的类就可以直接使用这些成员,但这些成员仍然受到对象范围的保护,不可被对象直接调用使用。

要声明一个成员成为受保护的成员,就使用"protected"关键字,下面这个程序是个实际的例子,您将数据成员声明为受保护的成员,继承它的类就可以直接使用,而不用透过"public"方法成员来调用:

  • Rectangle.java
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; }
}
  • Cubic.java
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; }
}
  • UseProtected.java
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)中的其它类直接存取。