Java编程思想之多态

来源:互联网 发布:dede cms 编辑:程序博客网 时间:2024/06/17 07:39

①多态通过分离做什么和怎么做,从另一角度将接口和实现分离开来。多态不但能够改善代码的组织结构和可读性。还能够创建可拓展的程序。
②“封装”通过合并特征和行为来创建新的数据类型。“实现隐藏”则通过将细节“私有化”把接口和实现分离开来。
③多态的作用则是消除类型之间的耦合关系。
④继承允许将对象视为它自己本身的类型或其基类型来加以处理。这种能力极为重要,因为它允许将多种类型(从同一基类导出的)视为同一类型来处理,而同一份代码也可以毫无差别地运行在这些不同类型之上。
⑤多态方法调用允许一种类型表现出与其它相似类型之间的区别。只要它们都是从同一基类导出而来的。这种区别是根据方法行为的不同而表示出来的,虽然这些方法都可以通过同一个基类来调用。
⑥多态是一项让程序员“将改变的事物与未变的事物分离开来”的重要技术。


那么编译器怎样才能知道基类的引用具体是指向哪一个派生类的呢?

①方法调用绑定

将一个方法调用同一个方法主体关联起来称作绑定。若在程序执行前进行绑定(如果有的话,由编译器和连接程序实现),叫做前期绑定。运行时根据对象的类型进行绑定,称为后期绑定,也叫做动态绑定或运行时绑定。
Java中除了static方法和final方法(private方法属于final方法)之外,其他所有的方法都是后期绑定。
一旦知道Java中所有的方法都是通过动态绑定实现多态这个事实之后,我们就可以编写只与基类打交道的代码了。(发送消息给某个对象,让该对象去断定应该做什么事。

②只有普通的方法调用可以是多态的

任何域访问操作都将由编译器解析,因此不是多态的。
只有非private方法才可以被覆盖,因此在导出类中同基类private方法相同名的方法是一个全新的方法。
如果某个方法是静态的,它的行为就不具有多态性,静态方法是与类,而并非与单个的对象相关联的。

③构造器内部的多态方法的行为

这里通过一个程序来说明问题:

class Glyph{    void draw(){        System.out.println("Glyph.draw()");    }    public Glyph(){        System.out.println("Glyph() before draw()");        draw(); //尝试修改为this.draw(),结果一样,this指的是当前对象。        System.out.println("Glyph() after draw()");    }}class RoundGlyph extends Glyph{    private int radius = 1;    RoundGlyph(int radius){        this.radius = radius;        System.out.println("RoundGlyph.RoundGlyph() radius="+this.radius);    }    void draw(){        System.out.println("RoundGlyph.draw() radius="+radius);    }}public class PolymorphicConstructors{    public static void main(String[] args){        new RoundGlyph(5);    }}/*运行结果为:Glyph() before draw()RoundGlyph.draw() radius=0  //radius 不是默认初始值1,而是零Glyph() after draw()RoundGlyph.RoundGlyph() radius=5*/

初始化的实际过程是:
1)在其他任何事物发生之前,将分配给对象的存储空间初始化成二进制的零。
2)调用基类构造器。此时调用被覆盖后的draw()方法(要在调用RoundGlyph构造器之前调用),由于步骤1的缘故,我们此时会发现radius的值为0.
3)按照声明的顺序调用成员的初始化方法。
4)调用导出类的构造器主体。


编写构造器时有一条有效的准则:“用尽可能简单的方法使对象进入正常状态;如果可以的话,尽量避免调用其他方法”。在构造器内唯一能安全调用的那些方法是基类中的final方法(也适用于private方法,它们自动属于final方法)。这些方法不能被覆盖,因此也就不会出现上述令人惊讶的问题。

### ④协变返回类型

Java SE5中添加了协变返回类型,它表示在导出类中的被覆盖方法可以返回基类方法的返回类型的某种导出类型。协变返回类型允许返回更具体的类型(返回类型的子类)。

用继承表达行为间的差异,并用字段表达状态上的变化

原创粉丝点击