黑马程序员技术交流社区

标题: 多态总结 [打印本页]

作者: 范泰洋    时间: 2012-10-13 00:52
标题: 多态总结
多态:
可以理解为事物存在的多种体现形态。


多态体现:
        父类的引用指向了自己的子类对象。
        父类的引用也可以接收自己的子类对象。
       
多态的前提:
        必须是类与类之间有关系,要么继承,要么实现。
    通常还有一个前提:存在覆盖。

多态的好处:
        多态的出现大大的提高程序的扩展性。

多态的弊端:
        提高了扩展性,但是只能使用父类的引用访问父类中的成员。

5.多态中成员的特点:



父类引用不能调用子类对象特有的数据。
如果想要调用子类多想的特有方法时,如何操作?
强制将父类的引用,转成子类类型。
我们能转换的是父类引用指向了自己的子类对象时,该引用可以被提升,也可以被强制转换。
多态自始至终都是子类对象在做着变化。


多态的向上转型和向下转型例子如下:

abstract class Person2{
        public abstract void sleep();
}


class Student2 extends Person2{
        public void sleep(){
                System.out.println("zZzZ!");
        }
       
        public void playGame(){
                System.out.println("DNF");
        }

}


class Student3 extends Person2{
        public void sleep(){
                System.out.println("good sleep!");
        }
       
        public void smoking(){
                System.out.println("smoking!");
        }
       
}

public class duotaiDemo {

        /**
         * @param args
         */
        public static void main(String[] args) {
                // TODO Auto-generated method stub
                //Person2 p = new Student2();//向上转型,父类的引用型变量p指向了自己的子类对象,并且父类有sleep()的方法,子类也有,不过子类覆盖了父类的sleep()方法,那么运行的就是子类自己的sleep();
                //p.sleep();
               
                //Student2 t = (Student2)p;//向下转型,强制将父类的引用转换成了子类对象,子类就就可以调用自己特有的playGame()方法了。父类没有playGame()方法。
                //t.playGame();       
               
                method(new Student2());//将一个对象作为参数传递了。
                //method(new Student3());
        }
       
       
        public static void method(Person2 p3){//这个method方法接收了一个对象,那么就可以写成这样:Person p3 = new Studnet2();这里做了一个动作,向上转型了,Student2转换成了Person2.
                p3.sleep();
                if(p3 instanceof Student2){//对传入的对象进行一个判断,以免出现类型转换异常。p3引用用instancof来测试它所指向的对象是否是Student2类的一个实例。
                        Student2 s2 = (Student2)p3;
                        s2.playGame();
                }
                else if(p3 instanceof Student3){
                        Student3 s3 = (Student3)p3;
                        s3.smoking();
                }
        }
       
}

在多态中非静态成员函数的特点:
在编译时期:参阅引用型变量所属的类中是否有调用的方法。如果有,编译通过,如果没有编译失败。
在运行时期:参阅对象所属的类中是否有调用的方法。
简单总结就是:成员函数在多态调用时,编译看左边,运行看右边。
{个人理解:就是向上转型的时候,父类引用子类对象,在编译的时候先要查看父类中是否有调用的方法,然后再运行时期就要查阅子类中是否也有和父类一样的方法,并且覆盖了。运行后那就是覆盖后的结果。当想要调用子类自己特有的方法的时候,父类没有的,那就得向下转型,那才能调用子类特有的方法。}

在多态中,成员变量的特点:
无论编译和运行,都参考左边(引用型变量所属的类。)


在多态中,静态成员函数的特点:
无论编译和运行,都参考左边。
{综合理解:多态中,静态成员函数静态方法区中,而在静态方法区中只有类名的引用,就相当于类名点方法。一调用这个方法就绑定了这个方法的所属的类了。而非静态区中有this引用和super引用。如果当fu f = new zi()此时这个父类的引用f指向了子类对象,那么调用方法的是时候f.method()方法的时候就相当于new zi().method()。所以运行是的子类对象的方法。}


接口引用型变量指向自己的子类对象。这也是多态的表现!
interface MachineSlot{
        public void commectTV();
        public void runGame();
}


class GameMachine{
        public void Machine(){
                System.out.println("Machine run");
        }
       
        public void UseMachineSlot(MachineSlot m){//这里就相当于是 MachineSlot m = new GameCard();接口类型指向了自己的子类对象
                if(m!=null){
                        m.commectTV();
                        m.runGame();
                }
        }
}

class GameCard implements MachineSlot{
        public void runGame(){
                System.out.println("DNF Run");
        }

        @Override
        public void commectTV() {
                // TODO Auto-generated method stub
                        System.out.println("电视连接成功");
                }
}


public class DuotaiCase {

        /**
         * @param args
         */
        public static void main(String[] args) {
                // TODO Auto-generated method stub
                GameMachine gm = new GameMachine();
                gm.Machine();
                gm.UseMachineSlot(null);
                gm.UseMachineSlot(new GameCard());
        }

}





欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2