按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
成员。但现在不必关心这方面的问题。
(4) 提供“访问器/变化器”方法(亦称为“获取/设置”方法),以便读取和修改值。这是OOP 环境中最
正规的一种方法,也是 Java Beans 的基础——具体情况会在第 13 章介绍。
5。2。2 public :接口访问
使用public 关键字时,它意味着紧随在public 后面的成员声明适用于所有人,特别是适用于使用库的客户
程序员。假定我们定义了一个名为 dessert 的包,其中包含下述单元(若执行该程序时遇到困难,请参考第
3 章 3。1。2 小节“赋值”):
//: Cookie。java
// Creates a library
package c05。dessert;
public class Cookie {
public Cookie() {
System。out。println(〃Cookie constructor〃);
}
void foo() { System。out。println(〃foo〃); }
} ///:~
请记住,Cookie。java 必须驻留在名为dessert 的一个子目录内,而这个子目录又必须位于由 CLASSPATH 指
定的C05 目录下面(C05 代表本书的第 5 章)。不要错误地以为 Java 无论如何都会将当前目录作为搜索的起
点看待。如果不将一个“。”作为CLASSPATH 的一部分使用,Java 就不会考虑当前目录。
现在,假若创建使用了 Cookie 的一个程序,如下所示:
//: Dinner。java
// Uses the library
import c05。dessert。*;
public class Dinner {
public Dinner() {
System。out。println(〃Dinner constructor〃);
}
public static void main(String'' args) {
Cookie x = new Cookie();
//! x。foo(); // Can't access
}
} ///:~
就可以创建一个Cookie 对象,因为它的构建器是 public 的,而且类也是public 的(公共类的概念稍后还会
进行更详细的讲述)。然而,foo()成员不可在 Dinner。java 内访问,因为foo()只有在 dessert包内才是
“友好”的。
1。 默认包
大家可能会惊讶地发现下面这些代码得以顺利编译——尽管它看起来似乎已违背了规则:
131
…………………………………………………………Page 133……………………………………………………………
//: Cake。java
// Accesses a class in a separate
// pilation unit。
class Cake {
public static void main(String'' args) {
Pie x = new Pie();
x。f();
}
} ///:~
在位于相同目录的第二个文件里:
//: Pie。java
// The other class
class Pie {
void f() { System。out。println(〃Pie。f()〃); }
} ///:~
最初可能会把它们看作完全不相干的文件,然而Cake 能创建一个 Pie 对象,并能调用它的 f()方法!通常的
想法会认为Pie 和f()是“友好的”,所以不适用于 Cake 。它们确实是友好的——这部分结论非常正确。但
它们之所以仍能在 Cake。java 中使用,是由于它们位于相同的目录中,而且没有明确的包名。Java 把象这样
的文件看作那个目录“默认包”的一部分,所以它们对于目录内的其他文件来说是“友好”的。
5。2。3 private :不能接触!
private 关键字意味着除非那个特定的类,而且从那个类的方法里,否则没有人能访问那个成员。同一个包
内的其他成员不能访问private 成员,这使其显得似乎将类与我们自己都隔离起来。另一方面,也不能由几
个合作的人创建一个包。所以 private 允许我们自由地改变那个成员,同时毋需关心它是否会影响同一个包
内的另一个类。默认的“友好”包访问通常已经是一种适当的隐藏方法;请记住,对于包的用户来说,是不
能访问一个“友好”成员的。这种效果往往能令人满意,因为默认访问是我们通常采用的方法。对于希望变
成public (公共)的成员,我们通常明确地指出,令其可由客户程序员自由调用。而且作为一个结果,最开
始的时候通常会认为自己不必频繁使用private 关键字,因为完全可以在不用它的前提下发布自己的代码
(这与C++是个鲜明的对比)。然而,随着学习的深入,大家就会发现private 仍然有非常重要的用途,特
别是在涉及多线程处理的时候(详情见第 14 章)。
下面是应用了private 的一个例子:
//: IceCream。java
// Demonstrates 〃private〃 keyword
class Sundae {
private Sundae() {}
static Sundae makeASundae() {
return new Sundae();
}
}
public class IceCream {
public static void main(String'' args) {
//! Sundae x = new Sundae();
Sundae x = Sundae。makeASundae();
132
…………………………………………………………Page 134……………………………………………………………
}
} ///:~
这个例子向我们证明了使用private 的方便:有时可能想控制对象的创建方式,并防止有人直接访问一个特
定的构建器(或者所有构建器)。在上面的例子中,我们不可通过它的构建器创建一个Sundae 对象;相反,
必须调用makeASundae ()方法来实现(注释③)。
③:此时还会产生另一个影响:由于默认构建器是唯一获得定义的,而且它的属性是 private,所以可防止
对这个类的继承(这是第6 章要重点讲述的主题)。
若确定一个类只有一个“助手”方法,那么对于任何方法来说,都可以把它们设为private,从而保证自己
不会误在包内其他地方使用它,防止自己更改或删除方法。将一个方法的属性设为private 后,可保证自己
一直保持这一选项(然而,若一个句柄被设为 private,并不表明其他对象不能拥有指向同一个对象的
public 句柄。有关“别名”的问题将在第 12 章详述)。
5。2。4 protected :“友好的一种”
protected (受到保护的)访问指示符要求大家提前有所认识。首先应注意这样一个事实:为继续学习本书一
直到继承那一章之前的内容,并不一定需要先理解本小节的内容。但为了保持内容的完整,这儿仍然要对此
进行简要说明,并提供相关的例子。
protected 关键字为我们引入了一种名为“继承”的概念,它以现有的类为基础,并在其中加入新的成员,
同时不会对现有的类产生影响——我们将这种现有的类称为“基础类”或者“基本类”(Base Class)。亦
可改变那个类现有成员的行为。对于从一个现有类的继承,我们说自己的新类“扩展”(extends)了那个现
有的类。如下所示:
class Foo extends Bar {
类定义剩余的部分看起来是完全相同的。
若新建一个包,并从另一个包内的某个类里继承,则唯一能够访问的成员就是原来那个包的 public 成员。当
然,如果在相同的包里进行继承,那么继承获得的包能够访问所有“友好”的成员。有些时候,基础类的创
建者喜欢提供一个特殊的成员,并允许访问衍生类。这正是protected 的工作。若往回引用5。2。2 小节
“public:接口访问”的那个Cookie。java 文件,则下面这个类就不能访问“友好”的成员:
//: ChocolateChip。java
// Can't access friendly member
// in another class
import c05。dessert。*;
public class ChocolateChip extends Cookie {
public ChocolateChip() {
System。ou