Java-多态

来源:互联网 发布:淘宝宝贝主图是什么 编辑:程序博客网 时间:2024/06/12 01:05
多态出现的缘由:Java的引用变量有两种类型:一个是编译时的类型,一个是运行时类型。
    (1) 编译时类型:声明该变量时使用的类型决定。 编译时动态重载;
    (2) 运行时类型:实际赋给该变量的对象决定,    指一个对象可以具有多个类型,方法的覆盖
如果编译时和运行时类型不一样就会出现所谓的多态(polymorphism)。
    理解运行时多态: 
    Car c = new Bus(); 
    Car编译时类型 编译时检查变量类型是否存在,是否有调用的方法。 
    Bus运行时类型  实际运行是访问heap中的对象,调用实际的方法。 
    运行时多态是由运行时类型决定的 
    编译时多态是由编译时类型决定的




多态:相同类项的变量执行同一个方法时,呈现出不同的行为特征这就是多态。


注意:引用变量在编译阶段只能调用其编译时类项所具有的方法,但运行时则执行运行时类项所具有的方法,
      因此编译java代码时,引用变量只能调用声明该变量时类项里包含的方法,
      如:Object p = new Person()定义一个变量p,p只能调用Object类得方法而不能调用person类里定义的方法。


      与方法不同的是对象的属性则不具有多态性:




多态 == 晚绑定。
不要把函数重载理解为多态。因为多态是一种运行期的行为,不是编译期的行为。


多态:父类型的引用可以指向子类型的对象。
    比如 Parent p = new Child();
当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误;
如果有,再去调用子类的该同名方法。
(注意此处,静态static方法属于特殊情况,静态方法只能继承,不能重写Override,如果子类中定义了同名同形式的静态方法,它对父类方法只起到隐藏的作用。调用的时候用谁的引用,则调用谁的版本。)
如果想要调用子类中有而父类中没有的方法,需要进行强制类型转换,如上面的例子中,将p转换为子类Child类型的引用。
因为当用父类的引用指向子类的对象,用父类引用调用方法时,找不到父类中不存在的方法。这时候需要进行向下的类型转换,将父类引用转换为子类引用。 


多态是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量倒底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。因为在程序运行时才确定具体的类,这样,不用修改源程序代码,就可以让引用变量绑定到各种不同的类实现上,从而导致该引用调用的具体方法随之改变,即不修改程序代码就可以改变程序运行时所绑定的具体代码,让程序可以选择多个运行状态,这就是多态性。多态性增强了软件的灵活性和扩展性。


 


多态性:发送消息给某个对象,让该对象自行决定响应何种行为。 通过将子类对象引用赋值给超类对象引用变量来实现动态方法调用。


java 的这种机制遵循一个原则:当超类对象引用变量引用子类对象时,被引用对象的类型而不是引用变量的类型决定了调用谁的成员方法, 但是这个被调用的方法必须是在超类中定义过的,也就是说被子类覆盖的方法。




package java8;
class A {
public String show(D obj) {return ("A and D"); }
public String show(A obj) {return ("A and A"); }
}
class B extends A {
public String show(B obj) {return ("B and B"); }
public String show(A obj) {return ("B and A"); }
}
class C extends B {}
class D extends B {}
public class Main {
public static void main(String[] args) {
A a1 = new A();
A a2 = new B();
B b = new B();
C c = new C();
D d = new D();
B e = new C();
System.out.println(a1.show(b) +" == A and A");   // A and A   b是B类对象也是A类对象,b是A的子类,就是说B也是一个A,调用class A的show(A obj)方法
System.out.println(a1.show(c) +" == A and A");   // A and A   c是C类对象也是A类对象
System.out.println(a1.show(d) +" == A and D");   // A and D   d是D类对象  传来一个D对象,当然调用的是A类的show(D obj)方法 
System.out.println(a2.show(b) +" == B and A");   // B and A   调用A类的show(A obj)方法被B类方法覆盖 注意这里,它首先在A类的方法里找到可以匹配的函数,然后发现子类重写了该方法,就调用子类,也就是B类的 show(A obj)方法,注意B类的 show(B obj),它是调用不了的,因为这是B类的特有方法,在A类里没有这个方法,也就没有重写
System.out.println(a2.show(c));   // B and A
System.out.println(a2.show(d));   // A and D
System.out.println(b.show(b));    // B and B
System.out.println(b.show(c));    // B and A
System.out.println(b.show(d));    // A and D
}
}


/**
 * java调用方法过程如下:
 * 编译时根据变量类型(包括方法调用者变量和方法参数变量的类型确定调用何种方法,记住不是实际类型,而是变量指定类型,因为它是编译时决定)。
 * 运行时根据实际调用方法的对象中查找参数和名称都对的上的覆盖的子类方法
 * 
 * 
 * 使用父类类型的引用指向子类的对象,该引用调用的是父类中定义的方法和变量,变量不能被重写(覆盖);如果子类中重写了父类中的一个方法,那么在调用这个方法的时候,将会调用子类中的这个方法;
 * 注意特殊情况,如果该父类引用所调用的方法参数列表未定义,就调用该父类的父类中查找,如果还没找到就强制向上类型转换参数列表中的参数类型,具体优先级高到低依次如下:
 * 优先级由高到低依次为:this.show(O)、    super.show(O)、    this.show((super)O)、    super.show((super)O)
 * 
 * 
 * 运行时多态性是面向对象程序设计代码重用的一个最强大机制,Java多态性的概念也可以被说成“一个接口,多个方法”。
 * Java实现运行时多态性的基础是动态方法调度,它是一种在运行时而不是在编译期调用重载方法的机制。
 * 方法的重写Overriding和重载Overloading是Java多态性的不同表现。重写Overriding是父类与子类之间多态性的一种表现,重载Overloading是一个类中多态性的一种表现。
 * 如果在子类中定义某方法与其父类有相同的名称和参数,我们说该方法被重写(Overriding)。子类的对象使用这个方法时,将调用子类中的定义,对它而言,父类中的定义如同被“屏蔽”了。
 * 如果在一个类中定义了多个同名的方法,它们或有不同的参数个数或有不同的参数类型,则称为方法的重载(Overloading)。
 * Overloaded的方法是可以改变返回值的类型。
 * 方法的重写Overriding和重载Overloading是Java多态性的不同表现。重写Overriding是父类与子类之间多态性的一种表现,重载Overloading是一个类中Java多态性的一种表现。如果在子类中定义某方法与其父类有相同的名称和参数,我们说该方法被重写 (Overriding)。子类的对象使用这个方法时,将调用子类中的定义,对它而言,父类中的定义如同被“屏蔽”了。如果在一个类中定义了多个同名的方法,它们或有不同的参数个数或有不同的参数类型,则称为方法的重载(Overloading)。Overloaded的方法是可以改变返回值的类型。
 * 当超类对象引用变量引用子类对象时,被引用对象的类型而不是引用变量的类型决定了调用谁的成员方法,但是这个被调用的方法必须是在超类中定义过的,也就是说被子类覆盖的方法。 
 * (但是如果强制把超类转换成子类的话,就可以调用子类中新添加而超类没有的方法了。)
 * 
 */
0 0
原创粉丝点击