Java---08---多态性

多态:

可以理解为事物存在的多种体现形态。

人有什么形态,男人、女人。

多态是子类对象在做着变化。

 

猫 x = new 猫 ();

动物 x = new 猫();


这就是一个对象具有多种形态。X是猫类型,同时也是“动物”类型。

类型提升 : 把猫提升为动物类型。向上转型


1.多态的体现

父类的引用指向了自己的子类对象

父类的引用也可以接收自己的子类对象

2.多态的前提

必须是类与类之间有关系,要么继承,要么实现

存在覆盖

3.多态的好处

提高了程序的扩展性

4.多态的弊端

提高扩展性,但是只能使用父类的引用访问父类中的成员


 

 

静态绑定和动态绑定:

静态绑定:编译时期就可以确定所调用的方法。Java中 只有 final、static、private和构造方法属于静态绑定。

动态绑定:运行时才可以确定所调用的方法。

 

 

重载和覆盖:

方法重载:用在用一个类中,所谓的重载是 方法名相同,但是返回值和参数列表可以不同。在程序运行时,编译器会根据传递过来的参数自动选择适合这种参数类型的方法。

方法覆盖:用在继承中。父类的方法在子类中出现,且是一模一样的(包括返回值和参数列表)。

 

 

abstract class Animal
{
    abstract void eat ();
}

class Cat extends Animal
{
    public void eat ()
    {
        System.out.println("Cat.eat()");
    }
}

class Dog extends Animal
{
    public void eat()
    {
        System.out.println("Dog.eat()");
    }
}

public class Practice
{
    public static void main (String[] args)
    {

        Cat cat = new Cat();
        Dog dog = new Dog();

        cat.eat();
        dog.eat();


        Animal c = new Cat();//类型提升  向上转型
        c.eat();
        Animal d = new Dog();
        d.eat();


    }
}


 

 

Animal c = new Cat();
c.eat();
c.CatchMoushe();


编译失败:The method CatchMoushe() is undefined for the type Animal

 

将子类向上转型为父类类型后,该对象所能使用的方法只能是父类拥有的。

而运行时所调用的方法则是子类对象自己的。

 

如何实现cat的特有方法?

向下转型。

Cat a = (Cat)c; 

 

判断某一类型的引用是否是这个类型 :instanceof

 

if ( c instanceof Cat )
{
    ((Cat) c).CatchMoushe();
}


 

非静态在多态中成员函数的特点:

编译时期:参阅引用型变量所属的类中是否有调用的方法

如果有编译通过,没有则失败

运行时期:参阅对象所属的类中是否有调用的方法

 

非静态成员函数在多态调用时,编译看左边,运行看右边

就是说:子类中有的,就调用子类的方法,没有的就去父类中找。如果还没有,则是不会编译通过的。

 

在多态中成员变量的特点:编译运行都参考左边。

 

class Fu
{
    int num = 10;
}

class Zi extends Fu
{
    int num = 20;
}
class Main
{
    public static void main (String[] args)
    {
        Fu f = new Zi();
        Zi z = new Zi();

        System.out.println(f.num+"\n"+z.num);
    }
}




输出的结果是:

10

20

 

 

静态成员函数的特点:参考左边。

 

class Fu
{
    int num = 10;
    static void show ()
    {
        System.out.println("Fu.show()");
    }
}

class Zi extends Fu
{
    int num = 20;
    static void show ()
    {
        System.out.println("Zi.show()");
    }
}

class Main
{
    public static void main (String[] args)
    {
        Fu f = new Zi();
        Zi z = new Zi();
        f.show();
        z.show();
    }
}




输出结果:

Fu.show()

Zi.show()





在别人的文章中看到这么一个例子:



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 DuoTai {
	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();   
        System.out.println(a1.show(b));  // ①  
        System.out.println(a1.show(c));  // ②  
        System.out.println(a1.show(d));  // ③  
        System.out.println(a2.show(b));  // ④  
        System.out.println(a2.show(c));  // ⑤  
        System.out.println(a2.show(d));  // ⑥  
        System.out.println(b.show(b));   // ⑦  
        System.out.println(b.show(c));   // ⑧  
        System.out.println(b.show(d));   // ⑨
	}
}


输出结果:



/*

A and A   ①
A and A   ②
A and D   ③
B and A   ④
B and A   ⑤
A and D   ⑥
B and B   ⑦
B and B   ⑧
A and D   ⑨
*/


这个涉及到了方法调用的优先级问题

优先级由高到低依次是:

this.show(O)、

super.show(O)、

this.show((super)O)、

super.show((super)O)。

 

举个例子说明一下:

 

①:a1.show(b);

a1是A类的对象,先是 this.show(O) 调用的方法先去A类中找,传递的参数是b类对象,在A中没有该方法,那么按super.show(O)

来找 ,找A的父类,A没有父类,再接着执行this.show((super)O)  找b类的父类,b类的父类是A,在A类中有该方法、输出。

②:a1.show(c)

还是先到A中找方法,A中没有,找A的父类,A没父类,找C的父类,C的父类是B ,A中还是没有方法,再找A的父类中找B,A没父类

再找B的父类,B的父类是A,A中有该方法,输出。





郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。