太自由

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理
【15-1】面向对象-多态-好处&弊端&前提

//描述狗
class Dog extends Animal
{
    public void eat()
    {
        System.out.println("吃饭");
    }

    public void lookHome()
    {
        System.out.println("看家");
    }
}

//描述猫
class Cat extends Animal
{
    public void eat()
    {
        System.out.println("鱼");
    }

    public void catchMice()
    {
        System.out.println("抓老鼠");
    }
}

//进行抽取,将共性的功能抽取到父类Animal中。
abstract class Animal
{
    public abstract void eat();
}

class DogAndCatTest
{
    public static void main(String[] agrs)
    {
        //Dog d = new Dog();
        //method(d);

        Animal a = new Dog();
        method(a);
        

        //Cat c = new Cat();
        method(new Cat());
    }
/*
发现,每一个动物,都需要为这个动物单独定义一个功能。
让这个动物的对象去做事。
这个程序扩展性很差。
如何提高这个扩展性呢?
发现,既然是让动物去吃,无论是Dog还是Cat,
eat是它们的共性,于是就可以将eat进行抽取,抽取到父类中。

Dog是Animal中的一种。
Dog d = new Dog();
Ainmal a = new Dog();
Cat c = new Cat();
Animal aa = new Cat();
*/

//只要去建立Animal的引用,就可以接收所有的dog对象进来,让它们去eat
//提高了程序的扩展性。


public static void method(Animal a)
{
    a.eat();
}

/*

//接收Dog,让dog去做事
    public static void method(Dog d)
    {
        d.eat();
    }

//接收Cat让Cat去做事
    public static void method(Cat c)
    {
        c.eat();
    }
    
*/

}

========================================================================================================
//15-2的完整例子如下:

//抽象类 动物
abstract class Animal
{
    public abstract void eat();
}

//描述Dog
class Dog extends Animal
{
    public void eat()
    {
        System.out.println("吃饭");
    }
    public void lookHome()
    {
        System.out.println("看家");
    }
}

//描述猫
class Cat extends Animal
{
    public void eat()
    {
        System.out.println("鱼");
    }
    public void catchMice()
    {
        System.out.println("抓老鼠");
    }
}


class DuoTaiTest
{
    public static void main(String[] args) 
    {
        //Dog d = new Dog();
        //method(d);
        //Cat c = new Cat();
        //method(c);
        Animal a = new Dog();
        //method(a);
        a.eat();
        //Animal a1 = new Dog();
        //method(a1);
        if(a instanceof Dog)
        {
            Dog d = (Dog)a;
            d.lookHome();
        }
        
    }
    //public static void method(Animal a)
    //{
    //    a.eat();
    //}
}
===========================================================================================================15-2】面向对象-多态-转型
    //描述狗
class Dog extends Animal
{
    public void eat()
    {
        System.out.println("吃饭");
    }

    public void lookHome()
    {
        System.out.println("看家");
    }
}

//描述猫
class Cat extends Animal
{
    public void eat()
    {
        System.out.println("鱼");
    }

    public void catchMice()
    {
        System.out.println("抓老鼠");
    }
}

//进行抽取,将共性的功能抽取到父类Animal中。
abstract class Animal
{
    public abstract void eat();
}

/*
多态:体现
    父类的引用或者接口指向了自己的子类对象。
    Dog d = new Dog();  //Dog对象的类型是Dog类型。
    Animal a = new Dog(); //Dog对象的类型右边是Dog类型,左边是Animal类型。
    
    好处:
    提高了程序的扩展性。

    弊端:
    通过父类引用操作子类对象时,只能使用父类中已有的方法,不能操作子类特有的方法。

    前提:
    1,必须有关系,继承或实现。
    2,通常都有重写操作

    子类的特有方法如何调用呢?
    Animal a = new Dog(); //Animal是父类型,new Dog()是子类对象。
    但是父类型引用指向子类对象时,这就是让子类对象进行了类型的提升(向上转型),
    如果想要使用子类的特有方法,只有子类型可以用。
    可以向下转型,强制转换。
    Animal a = new Dog();
    a.eat();
    Dog d = (Dog)a;//将a转型为Dog类型。向下转型
    d.lookHome();  //此时就可以用这个子类的特有功能了。
    向下转型什么时候用?当需要使用子类型的特有内容时。

    注意:无论向上还是向下转型,最终都是子类对象做着类型的变化。

    向下转型的注意事项:
    Animal a = new Dog();
    //Cat c = (Cat)a; //向下转型因为不明确具体子类对象类型,所以容易引发ClassCastException异常。
    所以为了避免这个问题,需要在向下转型前,做类型判断。

    判断类型用的是关键字。instanceof
    if(a instanceof Cat) //a指向的对象类型是Cat类型。
    {
        //将a转型为Cat类型。
        Cat a = (Cat)a;
        c.catchMouse();
    }
    else if(a instanceof Dog)
    {
        Dog d = (Dog)a;
        d.lookHome();
    }


    转型总结
    1,什么时候向上转型呢?
        提高程序的扩展性,不关心子类型(子类型被隐藏)
        需要用子类的特有的方法吗?不需要,那就向上转型。
    2,什么时候使用向下转型呢?
        需要使用子类特有的方法时。
        但是一定要使用instaceof 进行类型的判断,避免发生ClassCastException异常



*/

class DogAndCatTest
{
    public static void main(String[] agrs)
    {
        Dog d = new Dog();
        
        method(d);

        Cat c = new Cat();
        method(c);
    }

    public static void method(Animal a)
    {
        a.eat();
    }
}




【15-2】面向对象-多态-举例

    //多态-举例
class 毕姥爷
{
    public void 讲课()
    {
        System.out.println("讲管理");
    }
    public void 钓鱼()
    {
        System.out.println("钓鱼");
    }
}

class 毕老师 extends 毕姥爷
{
    public void 讲课()
    {
        System.out.println("Java");
    }
    public void 看电影()
    {
        System.out.println("看电影");
    }
}

class DuoTaiTest
{
    public static void main(String[] args)
    {
        毕姥爷 x = new 毕老师();
        x.讲课();
        x.钓鱼();
        //x.看电影();//不行
        //想要使用毕老师的特有方法时,需要
        if(x instanceof 毕老师)
        {
            毕老师 y = (毕老师)x;
            y.看电影();
        }
    }
}

-----------------------------------------15-3】面向对象-多态-练习-笔记本电脑
=========================================================================================================
    //描述笔记本,用到了鼠标的功能。
class noteBook
{
    public void run()
    {
        System.out.println("notebook run");
    }

    public void useMouse(Mouse m)
    {
        if(m!=null)
        {
            m.open();
            m.close();
        }
    }
}

//描述鼠标。
class Mouse
{
    public void open()
    {
        System.out.println("mouse open");
    }
    public void close()
    {
        System.out.println("mouse close");
    }
}


class NoteTest 
{
    public static void main(String[] args) 
    {
        noteBook b = new noteBook();
        b.run();
        b.useMouse(new Mouse());
    }
}
==========================================================================================
    /*
阶段一需要,笔记本电脑运行。
按照面向对象的思想,用代码体现。
名称提炼法。
笔记本电脑。
    行为,运行。

class HoteBook
{
    //运行功能
    public void run()
    {
        System.out.println("notebook run");
    }
}

阶段二需求:想要在笔记本电脑上加上一个手提式鼠标。
多了个对象,鼠标。
    行为:开启,关闭。

class Mouse
{
    public void open()
    {
        System.out.pritnln("mouse open");
    }
    public void close()
    {
        System.out.println("mouse close");
    }
}



//笔记本怎么用这鼠标呢?
在笔记本中多一个使用鼠标的功能.
需要修改原来的笔记本类中的内容,添加一个功能。

class NoteBook
{
    //运行功能
    public void run()
    {
        System.out.println("notebook run");
    }

    //使用鼠标的功能
    public void useMouse(Mouse m)
    {
        if(m!=null)
        {
            m.open();
            m.close();
        }
    }
}

//如果想要加入键盘呢?
*/
class Mouse
{
    public void open()
    {
        System.out.println("mouse open");
    }
    public void close()
    {
        System.out.println("mouse close");
    }
}
class NoteBook
{
    //运行功能
    public void run()
    {
        System.out.println("notebook run");
    }

    //使用鼠标的功能
    public void useMouse(Mouse m)
    {
        if(m!=null)
        {
            m.open();
            m.close();
        }
    }
}
class DuoTaiTest2
{
    public static void main(String[] args) 
    {
        NoteBook book = new NoteBook();
        book.run();
        book.useMouse(new Mouse());
        
    }
}
--------------------------------------------15-4】面向对象-多态-成员变量&成员函数&静态函数的特点
===================================================================================================
/*
多态中,成员调用的特点。

1,成员变量。
    当子父类中出现了同名的成员变量时,
        多态调用该变量时。
            编译时期,参考的是引用变量所属的类中是否有被调用的成员变量,没有,编译失败。
            运行时期,也是调用引用变量所属的类中的成员变量。

        简单记:编译和运行都参考等号左边
                编译运行看左边

2,成员函数。
     编译,参考左边,如果没有,编译失败。
     运行,参考右边的对象所属的类。
          编译看左边,运行看右边。如果子类没有和父类同名的那个函数,则运行的是父类的那个函数。
    
    对于成员函数是动态绑定对到对象上。

3,静态函数。
    对于静态成员函数,编译和运行都参考左边。

    对于静态函数是静态的绑定到类上。
*/

//结论:
//对于成员变量和静态函数,编译和运行都看左边。
//对于成员函数,编译看左边,运行看右边。

class Fu
{
    int num = 3;
    void show()
    {
        System.out.println("fu show run");
    }

    static void method()
    {
        System.out.println("fu static method run");
    }
}
class Zi extends Fu
{
    int num = 5;
    void show()
    {
        System.out.println("zi show run");
    }
    static void method()
    {
        System.out.println("zi static method run");
    }
}

class DuoTaiDemo
{
    public static void main(String[] args) 
    {
        /* 
        //测试成员变量的多态调用
        Fu f = new Zi();
        System.out.println(f.num);  //3
        Zi z = new Zi();
        System.out.println(z.num);  //5
        */
        
        /*
        //测试成员变量的多态调用
        Fu f = new Zi();
        f.show();   //结果:zi show run;
        */

        //测试静态函数的多态调用。
        Fu f = new Zi();
        f.method();
        
        //注意:真正开发静态方法是不会被多态调用的,因为静态方法不所属于对象,而是所属于类的。
        Fu.method();
    }

}

 

posted on 2016-02-23 09:06  太自由  阅读(251)  评论(0编辑  收藏  举报