多態(tài)polymorphism,向上轉(zhuǎn)型和動(dòng)態(tài)方法調(diào)度有什么用
多態(tài)有什么用?馬 克 - t o - w i n:我給大家想了兩個(gè)需求: 1)要求程序運(yùn)行起來(lái)以后,如果用戶輸入自行車,就執(zhí)行自行車的駕駛方法。如果用戶輸入小轎車,就執(zhí)行小轎車的駕駛方法。這是就用到父類指針指向子類時(shí)的 override。2)如果你有一千個(gè)子類。要求你依次執(zhí)行這一千個(gè)子類當(dāng)中的打印。你當(dāng)然可以一個(gè)一個(gè)實(shí)例化子類后分別執(zhí)行。馬克-to-win:累也累死了,你可以編一個(gè)循環(huán)。用通用的基類指向所有的派生類。幾行程序即可,你可以參照本節(jié)的例子。不用這技術(shù), 還真解決不了這問(wèn)題!
馬克- to-win:馬克 java社區(qū):防盜版實(shí)名手機(jī)尾號(hào): 73203。
Polymorphism means one type,many form
Dynamic method binding(dynamic method dispatch),方法覆蓋僅在兩個(gè)方法的名稱和類型聲明都相同時(shí)才發(fā)生(override)。
動(dòng)態(tài)方法調(diào)度(dynamic method dispatch)是一種在運(yùn)行時(shí)而不是編譯時(shí)調(diào)用方法的機(jī)制。
動(dòng)態(tài)方法調(diào)度也是Java實(shí)現(xiàn)運(yùn)行時(shí)多態(tài)性的基礎(chǔ)。 馬克-to-win:要想實(shí)現(xiàn)多態(tài),父類和子類必須同時(shí)擁有這個(gè)同名函數(shù)。否則實(shí)現(xiàn)不了多態(tài), 底下給出了例子,說(shuō)明這點(diǎn)。note that when
1)base pointer point to derived class to realize dynamic dispatching,an important requirement is that you also need to
have the same-name method in the base class.refer to the following example of SuperClass.
抽象類和非抽象類二者都可以用來(lái)創(chuàng)建對(duì)象引用,馬克-to-win:用來(lái)指向一個(gè)子類對(duì)象,實(shí)現(xiàn)多態(tài)。note that abstract and non-abstract class both can dynamically bind for example the following example.
例1.8.1---本章源碼
abstract class FigureMark {
double dime1;
double dime2;
/*這里的構(gòu)造函數(shù),是為子類調(diào)用使的,不是用來(lái)實(shí)例化的。馬克-to-win: constructor is for subclass's constructor's calling, not for
instantiating. */
FigureMark(double a, double b) {
dime1 = a;
dime2 = b;
}
// area is now an abstract method
abstract void area();
}
class RectangleMark extends FigureMark {
RectangleMark(double a, double b) {
super(a, b);
}
// 覆蓋
void area() {
System.out.println("四邊形" + dime1 * dime2);
}
}
class TriangleMark extends FigureMark {
TriangleMark(double a, double b) {
super(a, b);
}
void area() {
System.out.println("三角形." + dime1 * dime2 / 2);
}
}
public class Test {
public static void main(String args[]) {
// FigureMark f = new FigureMark(10, 10); // 錯(cuò),illegal now
RectangleMark r = new RectangleMark(9, 5);
TriangleMark t = new TriangleMark(10, 8);
FigureMark figref; // 沒(méi)事,this is OK, no object is created
figref = r;
figref.area();
figref = t;
figref.area();
/* 基類指針指向派生類的最大意義就在于此, */
FigureMark[] aa = { r, t };
for (int i = 0; i < aa.length; i++) {
aa[i].area();
}
/* 基類指針指向派生類的最大意義就在于此,馬克-to-win:否則你能像下面這樣自動(dòng)話嗎?計(jì)算機(jī)的最大意義不就是自動(dòng)化, 提高效率嗎? */
FigureMark[] aa1 = { new RectangleMark(9, 5), new TriangleMark(10, 8) };
for (int i = 0; i < aa1.length; i++) {
aa1[i].area();
}
}
}
result is:
四邊形45.0
三角形.40.0
四邊形45.0
三角形.40.0
四邊形45.0
三角形.40.0
對(duì)于以上例子,r不能指向TriangleMark,t不能指向RectangleMark,而 figref能指向上述二者,這就是基類指針的意義。馬 克-to- win:1)for the abve example, r can not point to TriangleMark,while t can not point to RectangleMark, while figref can point to above both, this is the point of the base pointer.
2)注意數(shù)組的效果是非常明顯的。
完全把上面的abstract去掉也行, 見(jiàn)下面:
例1.8.2---本章源碼
class FigureMark {
double dime1;
double dime2;
FigureMark(double a, double b) {
dime1 = a;
dime2 = b;
}
void area(){};//非抽象方法,得加個(gè)大括號(hào)
}
class RectangleMark extends FigureMark {
RectangleMark(double a, double b) {
super(a, b);
}
// 覆蓋
void area() {
System.out.println("四邊形" + dime1 * dime2);
}
}
class TriangleMark extends FigureMark {
TriangleMark(double a, double b) {
super(a, b);
}
void area() {
System.out.println("三角形." + dime1 * dime2 / 2);
}
}
public class Test {
public static void main(String args[]) {
FigureMark f = new FigureMark(10, 10); // 現(xiàn)在不錯(cuò)了
RectangleMark r = new RectangleMark(9, 5);
TriangleMark t = new TriangleMark(10, 8);
FigureMark figref; // 沒(méi)事,this is OK, no object is created
figref = r;
figref.area();
figref = t;
figref.area();
/* 基類指針指向派生類的最大意義就在于此, */
FigureMark[] aa = { r, t };
for (int i = 0; i < aa.length; i++) {
aa[i].area();
}
/* 基類指針指向派生類的最大意義就在于此,馬克-to-win:否則你能像下面這樣自動(dòng)話嗎?計(jì)算機(jī)的最大意義不就是自動(dòng)化, 提高效率嗎? */
FigureMark[] aa1 = { new RectangleMark(9, 5), new TriangleMark(10, 8) };
for (int i = 0; i < aa1.length; i++) {
aa1[i].area();
}
}
}
結(jié)果是:
四邊形45.0
三角形.40.0
四邊形45.0
三角形.40.0
四邊形45.0
三角形.40.0
例1.8.3: 要想實(shí)現(xiàn)多態(tài),父類和子類必須同時(shí)擁有這個(gè)同名函數(shù)。馬克-to-win:否則實(shí)現(xiàn)不了多態(tài),
---本章源碼
class SuperClassM_t_w {
public void printAsuper() {
System.out.println("父類中a =");
}
}
class SubClass extends SuperClassM_t_w {
public void printA() {
System.out.println("子類中a = " );
}
}
public class Test {
public static void main(String args[]) {
SuperClassM_t_w s1 = new SubClass();
// s1.printA();錯(cuò)誤, 因?yàn)榛愔袥](méi)有printA()這個(gè)方法,馬克-to-win:出現(xiàn)這種問(wèn)題,怎么解決,見(jiàn)下面的例子
}
}
final keyword
防止方法被覆蓋 Prevent method overriding
public class A{
public final void show(){
…
}
}
防止類被繼承,Prevent class inheritance
public final class A{
public void show(){
…
}
}
9.向下轉(zhuǎn)型Downcasting:(注意下面的理論沒(méi)涉及abstract)
Animal a1 = new Cat();
Animal a2 = new Dog();
Dog d = a2;//error必須要向下轉(zhuǎn)型一下
Cat c = a1;//error
Dog d = (Dog)a2;
Cat c = (Cat)a1;
假如我們寫成了如下, 就有問(wèn)題了:
Animal a1=new Animal();
Dog d=(Dog)a1; //底下做了個(gè)實(shí)驗(yàn)說(shuō)明了這點(diǎn)。馬克-to-win:這會(huì)報(bào)運(yùn)行時(shí)錯(cuò)誤,而不是編譯錯(cuò)誤。runtime error instead of compile error., because a1 is only animal,has no Dog的屬性.