Java编程思想第四版读书笔记——第八章 多态

来源:互联网 发布:淘宝搜索热词排名 编辑:程序博客网 时间:2024/06/03 17:41

本来不打算看了,现在面试笔试发现还是要重新拾起来看一遍。老老实实啃砖吧


 第八章 多态

在面向底下的程序设计语言中,多态是继数据抽象和继承之后的第三种基本特征。

“封装”通过合并特征和行为来创建新的数据类型。(合并成员函数和方法创建类)

“多态”消除类型之间的耦合关系。


1、向上转型

子类对象的引用向上转型为基类,传递到相应方法中。


2、转机

将一个方法调用同一个方法主体关联起来被称作绑定
程序执行前的绑定(由编译器和连接程序实现),称为前期绑定
运行时根据对象的类型进行绑定,称为后期绑定,也称为动态绑定或运行时绑定。
Java中除了static方法和final方法(private属于final方法)外,其它所有方法都是动态绑定。
多态让程序员将“改变的事物与未改变的事物分离开来”。
只有非private方法才能被覆盖,当然覆盖private类时,编译器不会报错。但是导出类和基类中的该同名方法,是两个不同的方法,向上转型为基类调用时,会调用基类的那个private的方法。

静态方法是与类,而非单个对象关联的,因此不是多态的。

任何访问操作都有编译器解析,因此不是多态的。

当Sub对象转型为Super使用时,任何域访问操作都将由编译器解析,因此不是多态的。(在包含相同成员变量时,子类包含两个域,基类和自己的,当要调用基类中该重名成员变量时,系统不会多态的自动的调用基类的该变量,需要显式的指明super.成员变量。)


3、构造器和多态

当有多重继承关系时,调用构造器顺序:

基类构造器 -> 成员的初始化方法 -> 子类构造器

在销毁时,需要显式的调用基类的dispose()方法,销毁的顺序和初始化相反,包括字段的销毁顺序和申明的顺序相反。共享数据最后dispose()。

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

在初始化时,基类构造器中调用子类中覆盖的方法,此时子类的成员变量未赋值,如果此时对其操作可能会产生意想之外的结果。所以应该避免这样做。在构造器内唯一能够安全调用的事基类中的final方法。


4、协变返回类型

子类中被覆盖的方法可以返回基类方法所返回类型的子类,这样虽然返回值类型不同,但是也算覆盖。


5、用继承进行设计

组合更加灵活,首选组合。

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


状态设计模式

创建一个基类的引用,通过方法改变其所指向的对象类型(子类们),调用相同的方法,行为产生变化。(调用了相应子类的方法)。 这样可以实现动态灵活性。

如下所示:

import static net.mindview.util.Print.*;
class Actor {
public void act() {}
}
class HappyActor extends Actor {
public void act() { print("HappyActor"); }

}
class SadActor extends Actor {
public void act() { print("SadActor"); }
}
class Stage {
private Actor actor = new HappyActor();
public void change() { actor = new SadActor(); }
public void performPlay() { actor.act(); }
}
public class Transmogrify {
public static void main(String[] args) {
Stage stage = new Stage();
stage.performPlay();
stage.change();
stage.performPlay();
}
} /* Output:
HappyActor
SadActor


对于子类扩展基类接口的情况,向上转型后不能调用子类的不同于基类的新方法。

这样需要用到向下转型,在Java中,所有的转型都会对其进行检查。称为“运行时类型识别”(RTTT)如果转型正确,则转型成功;如果所转类型不是正确的类型,则转型失败,返回ClassCastException异常。

父类引用可以指向子类对象,子类引用不可以指向父类对象。
比如:

class Useful {
public void f() {}
public void g() {}
}
class MoreUseful extends Useful {
public void f() {}
public void g() {}
public void u() {}
public void v() {}
public void w() {}
}
public class RTTI {
public static void main(String[] args) {
Useful[] x = {
new Useful(),
new MoreUseful()
};
x[0].f();
x[1].g();
// Compile time: method not found in Useful:
//! x[1].u();
((MoreUseful)x[1]).u(); // Downcast/RTTI
((MoreUseful)x[0]).u(); // Exception thrown
}
}





0 0