控制对成员的访问权限有两个原因:
第一是为了使用户不要碰触那些他们不该碰触的部分,这些部分对于类内部的操作是必要的,但是它井不属于客户端程序员所需接口的一部分。因此,将方法和域指定成private,对客户端程序员而言是一种服务。因为这样他们可以很清楚地看到什么对他们重要,什么是他们可以忽略的。这样简化了他们对类的理解。
第二个原因,也是最重要的原因,是为了让类库设计者可以更改类的内部工作方式,而不必担心这样会对客户端程序员产生重大的影响。例如,最初可能会以某种方式创建一个类,然后发现如果更改程序结构,可以大大提高运行速度。
如果接口和实现可以被明确地隔离和加以保护,那么就可以实现这一目的,而不必强制客户端程序员重新编写代码。访问权限控制可以确保不会有任何客户端程序员依赖于某个类的底层实现的任何部分。
当具备了改变底层实施细节的能力时,不仅可以随意地改善设计,还可能会随意地犯错误,同时也就有了犯错的可能性。无论如何细心地计划并设计,都有可能犯错。当了解到您所犯错误是相对安全的时候,就可以更加放心地进行实验,也就可以更快地学会,更快地完成项目。
类的公共接口是用户真正能够看到的,所以这一部分是在分析和设计的过程中决定该类是否正确的最重要的部分。尽管如此,您仍然有进行改变的空间。如果在最初无法创建出正确的接口,那么只要不删除任何客户端程序员在他们的程序中已经用到的东西,就可以在以后添加更多的方法。
final数据
对于基本类型,final使数据恒定不变;而对于对象引用,final使引用恒定不变。一旦引用被初始化指向一个对象,就无法再把它改为指向另一个对象。然而,对象其自身却使可以改变的,Java并未提供使任何对象恒定不变的途径。这一限制同样适用与数组,它也是对象。
final方法
“覆盖”只有在某方法是基类的接口的一部分时才会出现。即,必须能将一个对象向上转型为它的基本类型并调用相同的方法。如果某方法为private,它就不是基类的接口的一部分。它仅是一些隐藏于类中的代码,只不过是具有相同的名称而已。但如果在导出类以相同的方法生成一个public、protected或包访问权限方法的话,该方法就不会产生在基类中出现的 “仅具有相同名称”的情况。此时,你并没有覆盖该方法,仅是生成了一个新的方法。由于 private方法无法触及而且能有效隐藏,所以除了把它看成是因为它所归属的类的组织结构的原因而存在外,其他任何事物都不需要考虑它。
继承和组合
继承和组合都能从现有类型生成新类型。组合一般是将现有类型作为新类型底层实现的一部分来加以复用,而继承复用的是接口。由于导出类具有基类接口,所以它可以向上转型至基类,这对多态来讲至关重要。
尽管面向对象编程对继承极为强调,但在开始一个设计时,一般应优先选择使用组合,只有在确实必要时才使用继承。因为组合更具灵活性。此外,通过对成员元类型使用继承技术(这里不理解。我觉得是组合技术。求解!)的添加技巧,可以在运行时改变那些成员对象的类型和行为。因此,可以在运行时改变组合而成的对象的行为。
在设计一个系统时,目标应该是找到或创建某些类,其中每个类都有具体的用途,而且既不会太大(包含太多的功能而难以复用),也不会太小(不添加其他功能就无法使用)。
多态中“覆盖”私有方法(参看final方法)
public class PrivateOverride{ private void f(){ System.out.println("private f()"); } public static void main(String a[]){ PrivateOverride po = new Derived(); po.f(); } } class Derived extends PrivateOverride{ public void f(){ System.out.println("public f()"); } }
我们所期望的输出是“public f( )”(输出却是"private f()”),但是由于private方法被自动认为就是final方法,而且对导出类是屏蔽的。因此,在这种情况下,Derived类中的f( ) 方法就是一个全新的方法;既然基类中f( ) 方法在子类Derived中不可见,因此也就没有被重载。
结论就是:只有非private方法才可以被重载;但是我们还需要密切注意重载private方法的现象,虽然编译不会出错,但是不会按照我们所期望的来执行。明白地说,在导出类中,对于基类中的private方法,我们最好用一个不同的名字。、