10多态_Object

10多态_Object

导语:

想到在写

  1. 引出了多态的好处。通过动物示例发现操作父类型可以提高扩展性
  2. 动物的示例,了解了多态的体现,好处,弊端,前提,向上向下转型,以及什么时候用?★★★★★
  3. 毕老师和毕姥爷的故事。将多态的知识点串一下。自动动手写!★★★★★
  4. 分三个阶段 完成笔记本电脑使用外围设备。并通过接口解耦,并通过多态提高程序的扩展性。★★★★★★★
  5. 多态调用时,成员变量,成员函数,静态函数的特点。以及规律
  6. 一定要画图,得出结果。有点难!没视频,★★★★★
  7. 了解Object类中的equals toString方法的使用

1. 引出了多态的好处。通过动物示例发现操作父类型可以提高扩展性

 //多态技术的引出。解决什么问题?程序扩展性的问题。
    
    //描述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 catchMouse()
        {
            System.out.println("抓老鼠");
        }
    }
    //进行抽取。将共性的功能抽取到父类Animal中。
    abstract class Animal
    {
        public abstract void eat();
    }
    
    
    
    class DuoTaiDemo
    {
        public static void main(String[] args) 
        {
            Dog d = new Dog();
    //        d.eat();
            method(d);
    
            Cat c = new Cat();
            method(c);
        }
        /*
        发现,每多一个动物,都需要为这个动物单独定义一个功能,
        让这个动物的对象去做事。
        这个程序扩展性就很差。
        如何提高这个扩展性呢?
        发现既然是让动作去eat,无论是dog,还是cat,
        eat是它们共性,干脆,将eat进行抽取。抽取到父类Animal中。
    
        Dog是Animal中的一种。
        Dog d = new Dog();
        Animal a = new Dog();
        Cat c = new Cat();
        Animal aa = new Cat();
        */
        //只要建立animal的引用就可以接收所有的dog cat对象进来。让它们去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();
        }
        */
    
    } 

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 catchMouse()
        {
            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 c = (Cat)a;
            c.catchMouse();
        }
        else if(a instanceof Dog)
        {
            Dog d = (Dog)a;
            d.lookHome();
        }
    
        【转型总结】
        1,什么时候使用向上转型呢?
            提高程序的扩展性,不关系子类型(子类型被隐藏)。
            需要用子类的特有方法吗?不需要,哦了。向上转型。
        2,什么时候使用向下转型呢?
            需要使用子类型的特有方法时。
            但是一定要使用 instanceof 进行类型的判断。避免发生 ClassCastException
    
    */
    
    class DuoTaiDemo2
    {
        public static void main(String[] args) 
        {
            Dog d = new Dog();
    //        d.eat();
    //        d.lookHome();
    
            /*
            Animal a = new Dog();
            a.eat();//可以的。
    //        a.lookHome();//不可以的。
            */
    
            method(d);
            Cat c = new Cat();
            method(c);
        }
        public static void method(Animal a)
        {
    
            a.eat();
    //        Dog d = (Dog)a;//ClassCastException:类型转换异常。
    //        d.lookHome();
    
    //        a.lookHome();//不可以,因为动物不具备这个功能。
        }
    
    } 

3. 毕老师和毕姥爷的故事。将多态的知识点串一下。自动动手写!★★★★★

 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.看电影();
            }
            //自始至终都是子类对象做着类型的变化。
    
    
        }
    } 

4. 分三个阶段 完成笔记本电脑使用外围设备。并通过接口解耦,并通过多态提高程序的扩展性。★★★★★★★

 /*
    阶段一需求:笔记本电脑运行。
    按照面向对象的思想,用代码体现。
    名称提炼法。
    笔记本电脑。
        行为:运行。
    
    class NoteBook
    {
        //运行功能。
        public void run()
        {
            System.out.println("notebook run");
        }
    }
    
    阶段二需求:想要在笔记本电脑上加上一个手握式鼠标。
    多了个对象:鼠标。
            行为:开启,关闭。
    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();
            }
        }
    }
    //问题:如果想要加入一个键盘呢?
    只要描述一个键盘类,并在电脑类中加入一个使用键盘的功能就哦了。
    但是发现从鼠标开始这个问题就已经产生了,一旦需要添加新设备的时候,
    都需要改变电脑的源码。这个扩展性是非常差的。
    
    设计上该如何改进呢?
    之前的问题在于外围设备的增加和笔记本电脑之间的耦合性过高。
    如何降低外围设备和笔记本电脑的耦合性呢?
    外围设备还不确定,我们不要面对外围具体设备。
    为了让笔记本可以使用这些设备,可以事先定义好一些规则,
    笔记本只要使用这些规则就可以了。
    有了这些规则就可以进行笔记本的功能扩展。
    后期这些外围设备只要符合这些规则就可以被笔记本使用了。
    
    那么规则在java中该如何体现呢?接口。
    
    //1,描述接口。USB。
    
    //2,描述笔记本电脑:运行功能,使用USB接口的功能。
    
    
    
    */
    //USB接口定义。
    interface USB
    {
        void open();
        void close();
    }
    
    //描述笔记本电脑。 
    class NoteBook
    {
        public void run()
        {
            System.out.println("notebook run");
        }
    
        //使用usb接口的功能。
        public void useUSB(USB usb)//接口类型的变量。接口类型的变量指向自己的子类对象。
                                    //USB usb = new Mouse();
        {
            if(usb!=null)
            {
                usb.open();
                usb.close();
            }
        }
    }
    //需要鼠标 。想要被笔记本电脑使用,该鼠标必须符合规则。
    //描述鼠标。
    class Mouse implements USB
    {
        public void open()
        {
            System.out.println("mouse open");
        }
        public void close()
        {
            System.out.println("mouse close");
        }
    }
    
    class KeyBoard implements USB
    {
        public void open()
        {
            System.out.println("KeyBoard open");
        }
        public void close()
        {
            System.out.println("KeyBoard close");
        }
    }
    
    /*
    发现,接口的出现,
    1,扩展了笔记本电脑功能。
    2,定义了规则。
    3,降低了笔记本电脑和外围设备之间的耦合性。
    */
    
    class DuoTaiTest2 
    {
        public static void main(String[] args) 
        {
            NoteBook book = new NoteBook();
            book.run();
            book.useUSB(null);
            book.useUSB(new Mouse());
            book.useUSB(new KeyBoard());
        }
    } 

5. 多态调用时,成员变量,成员函数,静态函数的特点。以及规律

 /*
    多态中,成员调用的特点。
    
    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 DuoTaiDemo3 
    {
        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();
            */
            //测试静态函数的多态调用。
            Fu f = new Zi();
            f.method();
            //注意:真正开发静态方法是不会被多态调用的,因为静态方法不所属于对象,而是所属于类。
            Fu.method();
            Zi.method();
        }
    } 

6. 一定要画图,得出结果。有点难!没视频,★★★★★

//练习:看程序画图,得出结果!
    class Fu
    {
        int x = 4;
        Fu()
        {
            System.out.println("A fu() : "+this.getNum());
        }
        int getNum()
        {
            System.out.println("B fu getnum run...."+x);
            return 100;
        }
    }
    class Zi extends Fu
    {
        int x = 5;
        Zi()
        {
            System.out.println("C zi() : "+getNum());
        }
        int getNum()
        {
            System.out.println("D zi getnum run...."+x);
            return 200;
        }
    }
    class DuoTaiTest3 
    {
        public static void main(String[] args) 
        {
            Fu f = new Zi();
            //System.out.println("main :" +f.getNum());
            //Person p = new Person(20):
        }
    } 

7. 了解Object类中的equals toString方法的使用

 /*
    Object类中的常用方法。
    
    Object类是所有类的根类,定义了所有对象都具备的功能。
    API(应用程序接口)文档
    
    */
    class Person extends Object
    {
        private int age;
        Person(int age)
        {
            this.age = age;
        }
        //判断是否是同龄人。这个方法也是在比较两个person对象是否相等。
        //注意:Person类中是否有比较两个Person对象相等的方法?有的!因为继承Object,它本身就具备着equals方法。
        //既然有,还需要定义compare方法吗?不需要。
        //但是,equals方法判断的是地址,不是我们所需要的内容。
        //咋办?继续使用Object的equals方法,但是建立子类的自己的内容。传说中的重写。
        //重写。
    //    【记住:以后判断对象是否相同,就需要覆盖equals方法。】
        public boolean equals(Object obj)
        {
    
            //建立Person自己的判断相同的依据。判断年龄是否相同。
    //        return this.age == obj.age;//obj所属类型Object,Object中没有定义age,所以编译失败。
    
            //如果调用该方法的对象和传递进来的对象是同一个。就不要转型和判断,直接返回true。效率高一点。
            if(this == obj)
                return true;
    
            //age是Person类型的属性。既然要用到子类型的内容,需要向下转型。
            if(!(obj instanceof Person))
    //            return false;
                throw new ClassCastException("类型是不对的!请改正。");
            Person p = (Person)obj;
    
            return this.age == p.age;
    
        }
    
        //覆盖toString方法,建立Person对象自己的字符串表现形式。
        public String toString()
        {
            return "Person[age = "+age+"]";
        }
    
        /*
        public boolean compare(Person p)
        {
            return this.age == p.age;
        }
        */
    }
    
    class Dog
    {
    }
    
    class ObjectDemo 
    {
        public static void main(String[] args) 
        {
            Person p1 = new Person(12);
            Person p2 = new Person(15);
    //        System.out.println(p1.equals(p2));
    
            System.out.println(p1.toString());//Person@da4b71//想要建立自定义对象的字符串表现实行。咋办、覆盖toString方法就哦了。
            System.out.println(p2);
    
    
    
    //        -----------------------------
    //        System.out.println(p1.compare(p2));
    //        System.out.println(p1 == p2);
    //        System.out.println(p1.equals(p2));
        }
    }
发布了21 篇原创文章 · 获赞 0 · 访问量 52

猜你喜欢

转载自blog.csdn.net/qq_42745404/article/details/105036811
今日推荐