多态polymorphism,向上转型和动态方法调度有什么用

多态有什么用?马 克  -   t   o - w   i  n:我给大家想了两个需求: 1)要求程序运行起来以后,如果用户输入自行车,就执行自行车的驾驶方法。如果用户输入小轿车,就执行小轿车的驾驶方法。这是就用到父类指针指向子类时的 override。2)如果你有一千个子类。要求你依次执行这一千个子类当中的打印。你当然可以一个一个实例化子类后分别执行。马克-to-win:累也累死了,你可以编一个循环。用通用的基类指向所有的派生类。几行程序即可,你可以参照本节的例子。不用这技术, 还真解决不了这问题!
马克- to-win:马克 java社区:防盗版实名手机尾号: 73203。



Polymorphism means one type,many form

Dynamic method binding(dynamic method dispatch),方法覆盖仅在两个方法的名称和类型声明都相同时才发生(override)。

动态方法调度(dynamic method dispatch)是一种在运行时而不是编译时调用方法的机制。
动态方法调度也是Java实现运行时多态性的基础。 马克-to-win:要想实现多态,父类和子类必须同时拥有这个同名函数。否则实现不了多态, 底下给出了例子,说明这点。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.

抽象类和非抽象类二者都可以用来创建对象引用,马克-to-win:用来指向一个子类对象,实现多态。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;
/*这里的构造函数,是为子类调用使的,不是用来实例化的。马克-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); // 错,illegal now
        RectangleMark r = new RectangleMark(9, 5);
        TriangleMark t = new TriangleMark(10, 8);
        FigureMark figref; // 没事,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:否则你能像下面这样自动话吗?计算机的最大意义不就是自动化, 提高效率吗? */       
        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

对于以上例子,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)注意数组的效果是非常明显的。




完全把上面的abstract去掉也行, 见下面:
例1.8.2---本章源码

class FigureMark {
    double dime1;
    double dime2;
    FigureMark(double a, double b) {
        dime1 = a;
        dime2 = b;
    }
    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); // 现在不错了
        RectangleMark r = new RectangleMark(9, 5);
        TriangleMark t = new TriangleMark(10, 8);
        FigureMark figref; // 没事,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:否则你能像下面这样自动话吗?计算机的最大意义不就是自动化, 提高效率吗? */      
        FigureMark[] aa1 = { new RectangleMark(9, 5), new TriangleMark(10, 8) };
        for (int i = 0; i < aa1.length; i++) {
            aa1[i].area();
        }
    }
}
结果是:
四边形45.0
三角形.40.0
四边形45.0
三角形.40.0
四边形45.0
三角形.40.0




例1.8.3: 要想实现多态,父类和子类必须同时拥有这个同名函数。马克-to-win:否则实现不了多态,

---本章源码

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();错误, 因为基类中没有printA()这个方法,马克-to-win:出现这种问题,怎么解决,见下面的例子
    }
}


final keyword
防止方法被覆盖 Prevent method overriding

public class A{
public final void show(){

}
}

防止类被继承,Prevent class inheritance
public final class A{
public void show(){

}
}
9.向下转型Downcasting:(注意下面的理论没涉及abstract)
Animal a1 = new Cat();
Animal a2 = new Dog();
Dog d = a2;//error必须要向下转型一下
Cat c = a1;//error
Dog d = (Dog)a2;
Cat c = (Cat)a1;

假如我们写成了如下, 就有问题了:

 Animal a1=new Animal();
          Dog d=(Dog)a1; //底下做了个实验说明了这点。马克-to-win:这会报运行时错误,而不是编译错误。runtime error instead of compile error., because a1 is only animal,has no Dog的属性.