本来不打算看了,现在面试笔试发现还是要重新拾起来看一遍。老老实实啃砖吧
在面向底下的程序设计语言中,多态是继数据抽象和继承之后的第三种基本特征。
“封装”通过合并特征和行为来创建新的数据类型。(合并成员函数和方法创建类)
“多态”消除类型之间的耦合关系。
子类对象的引用向上转型为基类,传递到相应方法中。
静态方法是与类,而非单个对象关联的,因此不是多态的。
任何域访问操作都有编译器解析,因此不是多态的。
当Sub对象转型为Super使用时,任何域访问操作都将由编译器解析,因此不是多态的。(在包含相同成员变量时,子类包含两个域,基类和自己的,当要调用基类中该重名成员变量时,系统不会多态的自动的调用基类的该变量,需要显式的指明super.成员变量。)
当有多重继承关系时,调用构造器顺序:
基类构造器 -> 成员的初始化方法 -> 子类构造器
在销毁时,需要显式的调用基类的dispose()方法,销毁的顺序和初始化相反,包括字段的销毁顺序和申明的顺序相反。共享数据最后dispose()。
在初始化时,基类构造器中调用子类中覆盖的方法,此时子类的成员变量未赋值,如果此时对其操作可能会产生意想之外的结果。所以应该避免这样做。在构造器内唯一能够安全调用的事基类中的final方法。
子类中被覆盖的方法可以返回基类方法所返回类型的子类,这样虽然返回值类型不同,但是也算覆盖。
组合更加灵活,首选组合。
用继承表达行为间的差异,用字段表达状态上的变化。
状态设计模式
创建一个基类的引用,通过方法改变其所指向的对象类型(子类们),调用相同的方法,行为产生变化。(调用了相应子类的方法)。 这样可以实现动态灵活性。
如下所示:
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
}
}