• 41.Java特征之一多态


    多态

    1.1    多态的概述

       1:什么是多态

          一个对象的多种状态

          (老师)(员工)(儿子)

          教师 a =老钟;

          员工 b= 老钟;

       2:多态体现

          1:Father类

              1:非静态成员变量x

              2:静态成员变量y

              3:非静态方法eat,方法体输出父类信息

              4:静态方法speak();方法体输出父类信息

          2:Son类

              1:非静态成员变量x

              2:静态成员变量y

              3:非静态方法eat,方法体输出子类信息

              4:静态方法speak();方法体输出子类信息

    class Father {
        int x = 1;
        static int y = 2;
    
        void eat() {
            System.out.println("开吃");
        }
    
        static void speak() {
            System.out.println("小头爸爸");
        }
    }
    
    class Son extends Father {
        int x = 3;
        static int y = 4;
    
        void eat() {
            System.out.println("大头儿子很能吃");
        }
    
        static void speak() {
            System.out.println("大头儿子。");
        }
    }
    
    class Demo10 {
    
        public static void main(String[] args) {
    
            Father f = new Son(); // 父类引用指向了子类对象。
            System.out.println(f.x); // 1
            System.out.println(f.y); // 2
    
            f.eat(); // 输出的是子类的。
            
            f.speak(); // 输出的是父类
            
        }
    }

    3:Son类继承父类

              1:创建Father f=new Son();

                 1:这就是父类引用指向了子类对象。

                 2:问f.x=?(非静态)

                 3:问f.y=?(静态)

                 4:问f.eat()输出的是子类还是父类信息?(非静态)

                 5:问f.speak()输出的是子类还是父类信息?(静态)

          4:总结

    1:当父类和子类具有相同的非静态成员变量,那么在多态下访问的是父类的成员变量

    2:当父类和子类具有相同的静态成员变量,那么在多态下访问的是父类的静态成员变量

              所以:父类和子类有相同的成员变量,多态下访问的是父类的成员变量。

    3:当父类和子类具有相同的非静态方法(就是子类重写父类方法),多态下访问的是子类的成员方法。

    4:当父类和子类具有相同的静态方法(就是子类重写父类静态方法),多态下访问的是父类的静态方法。

       2:多态体现

          1:父类引用变量指向了子类的对象

          2:父类引用也可以接受自己的子类对象

    3:多态前提

       1:类与类之间有关系,继承或者实现

    4:多态弊端

       1:提高扩展性,但是只能使用父类引用指向父类成员。

    5:多态特点

       非静态

    1:编译时期,参考引用型变量所属的类是否有调用的方法,如果有编译通过。没有编译失败

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

       3:总之成员函数在多态调用时,编译看左边,运行看右边。

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

       在多态中,静态成员函数特点,无论编译和运行都参考左边

    6:多态练习

       1:多态可以作为形参,接受范围更广的对象,避免函数重载过度使用。

          1:定义功能,根据输出任何图形的面积和周长。

              1:定义抽象类abstract MyShape

                 1:定义抽象方法public abstract double getArea();

                 2:定义抽象方法public abstract double getLen();

          2:定义Rect类继承MyShape

              1:定义长和宽成员变量,double width height;

              2:无参构造,有参构造。

              3:实现父类方法。

          3:定义Cricle类继承MyShape

              1:定义半径成员变量,和PI常量

              2:无参构造,有参构造

              3:实现父类方法。

          4:定义静态方法计算任意图形的面积和周长

              1:未知内容参与运算,不能确定用户传入何种图形,使用多态。

                 1:形参定义为 MyShape my

              2:调用计算面积方法,和计算周长方法。并打印

                 2:使用多态特性,子类重写了父类非静态方法,会执行子类的方法。

    /*
    多态练习
        1:多态可以作为形参,接受范围更广的对象,避免函数重载过度使用。
            1:定义功能,根据输出任何图形的面积和周长。
            子类重写了父类的抽象方法,多态下,会执行子类的非静态方法。
        2:多态可以作为返回值类型。
            获取任意一辆车对象
        3:抽象类和接口都可以作为多态中的父类引用类型。
    */
    abstract class MyShape{
        public abstract double getArea();
        public abstract double getLen();
    }
    class  Rect extends MyShape{
        double width ;
        double height;
        Rect(){
        
        }
        Rect(double width ,double height){
            this.width=width;
            this.height=height;
        }
        public double getArea(){
            return width*height;
        }
        public  double getLen(){
            return 2*(width+height);
        }
        
    }
    class Circle extends MyShape{
         double r;
         public static final double PI=3.14;
         
         Circle(){
         
         }
         
        Circle(double r){
             this.r=r;
         }
        public double getLen(){
             return 2*PI*r;
         }
        
        public double getArea(){
             return PI*r*r;
         }
    }
    
    class Demo11{
    
        public static void main(String[] args){
    
            System.out.println();
            
            print(new Rect(3,4)); //MyShape m =new Rect(3,4);
            
            print(new Circle(3));
            
             }
             
             //根据用户传入的图形对象,计算出该图形的面积和周长
             //1:多态可以作为形参,接受范围更广的对象,避免函数重载过度使用。 
             public static void print(MyShape m){  
                 System.out.println(m.getLen());
                 System.out.println(m.getArea());
             }       
    }

    2:多态可以作为返回值类型。

          获取任意一辆车对象

              1:定义汽车类,有名字和颜色,提供有参和无参构造,有运行的行为。

    2:定义Bmw类,继承Car类,提供无参构造和有参构造(super父类构造),重写父类运行行为。

    3:定义Benz类,继承Car类,提供无参构造和有参构造(super父类构造),重写父类运行行为。

    4:定义Bsj类,继承Car类,提供无参构造和有参构造(super父类构造),重写父类运行行为。

              5:定义静态方法,汽车工厂,随机生产汽车。使用多态定义方法返回值类型。

                 1:使用(int)Math.round(Math.random()*2); 生成0-2之间随机数。

                 2:使用if else 判断,指定,0,1,2 new 不同汽车 并返回。

              6:调用该方法,发现多态的好处。

    *
     2:多态可以作为返回值类型。
     获取任意一辆车对象
     1:定义汽车类,有名字和颜色,提供有参和无参构造,有运行的行为。
     2:定义Bmw类,继承Car类,提供无参构造和有参构造(super父类构造),重写父类运行行为。
     3:定义Benz类,继承Car类,提供无参构造和有参构造(super父类构造),重写父类运行行为。
     4:定义Bsj类,继承Car类,提供无参构造和有参构造(super父类构造),重写父类运行行为。
     5:定义静态方法,汽车工厂,随机生产汽车。使用多态定义方法返回值类型。
     1:使用(int)Math.round(Math.random()*2); 生成0-2之间随机数。
     Math 类
     2:使用if else 判断,指定,0,1,2 new 不同汽车 并返回。
     6:调用该方法,发现多态的好处。
     */
    class Car {
        String name;
        String color;
    
        Car() {
    
        }
    
        Car(String name, String color) {
            this.name = name;
            this.color = color;
        }
    
        void run() {
            System.out.println("跑跑。。。。");
        }
    }
    
    class Bmw extends Car {
        Bmw() {
    
        }
    
        Bmw(String name, String color) {
            super(name, color);
        }
    
        void run() {
            System.out.println("宝马很拉风。。。。");
        }
    }
    
    class Benz extends Car {
        Benz() {
    
        }
    
        Benz(String name, String color) {
            super(name, color);
        }
    
        void run() {
            System.out.println("奔驰商务首选。。。。");
        }
    }
    
    class Bsj extends Car {
    
        Bsj() {
    
        }
    
        Bsj(String name, String color) {
            super(name, color);
        }
    
        void run() {
            System.out.println("泡妞首选。。。。");
        }
    }
    
    class Demo12 {
    
        public static void main(String[] args) {
    
            int x = 0;
            while (x < 100) {
                Car c = CarFactory();
                c.run();
                x++;
            }
    
        }
    
        // 定义静态方法,汽车工厂,随机生产汽车。使用多态定义方法返回值类型。
        // 使用随机数,0.1.2 if 0 bsj 1 bmw 2 bc
        public static Car CarFactory() {
            int x = (int) Math.round(Math.random() * 2);
    
            if (0 == x) {
                return new Bmw("宝马x6", "红色");
            } else if (1 == x) {
                return new Benz("奔驰", "黑色");
            } else if (2 == x) {
                return new Bsj("保时捷", "棕色");
            } else {
                return new Benz("Smart", "红色");
            }
    
        }
    }

        3:抽象类和接口都可以作为多态中的父类引用类型。

              1:sun Arrays

    6:多态之类型转型

       1:案例定义Father类

          1:定义method1和method2方法

       2:定义Son类继承Father类

          1:定义method1(重写父类method1)和method2方法

       3:创建Father f=new Son();

          1: f.method1() 调用的子类或者父类?

          2: f.method2() 编译和运行是否通过?

          3: f.method3() 编译和运行是否通过?(编译报错)

       4:如何在多态下,使用父类引用调用子类特有方法。

          1:基本类型转换:

              1:自动:小->大

              2:强制:大->小

          2:类类型转换

              前提:继承,必须有关系

              1:自动:子类转父类

              2:强转:父类转子类

              3:类型转换

                 1:Son s=(Son)f

                 2:s.method3();

    /*
     如何在多态下,使用父类引用调用子类特有方法。
     1:基本类型转换:
     1:自动:小->大    int x=1 double d=x;
     2:强制:大->小    int y=(int)d;
     2:类类型转换
     前提:继承,必须有关系
     1:自动:子类转父类  Father f=new Son(); 
     2:强转:父类转子类  Son s=(Son)f;    
     1:类型转换
     1:Son s=(Son)f
     2:s.method3(); 
     */
    class Father {
    
        void method1() {
            System.out.println("这是父类1");
        }
    
        void method2() {
            System.out.println("这是父类2");
        }
    }
    
    class Son extends Father {
        void method1() {
            System.out.println("这是子类1");
        }
    
        void method3() {
            System.out.println("这是子类3");
        }
    }
    
    class Demo14 {
    
        public static void main(String[] args) {
            Father f = new Son();
            f.method1(); // 这是子类1
            f.method2(); // 这是父类2
    
            // f.method3(); //编译报错。
            // 多态弊端,只能使用父类引用指向父类成员。
    
            // 类类型转换
            Son s = (Son) f;
            s.method3();
    
            System.out.println();
        }
    }

    5:案例:

       1:定义Animal类颜色成员变量,无参构造,有参构造,run方法

    2:定义Dog类,继承Animal,定义无参构造,有参构造(使用super调用父类有参构造),Dog的特有方法ProtectHome

    3:定义Fish类,继承Animal,定义无参构造,有参构造(使用super调用父类有参构造),Fish特有方法swim

    4:定义Bird类,继承Animal,定义无参构造,有参构造(使用super调用父类有参构造),Bird特有方法fly

       5:使用多态,Animal a=new Dog();

       6:调用Dog的特有方法,ProtectHome

          1:类类型转换,Dog d=(Dog)a;

          2:d.protectHome

       7:非多态

          1:Animal a=new Animal();

          2:类类型转换

              Dog d=(Dog)a; 

              d.protectHome();

          3:编译通过,运行出现异常

              1:ClassCastException

       8:多态例外

              1:Animal  a=new Dog();

              2:类类型转换

                 1:Fish f=(Fish)a;

                 2:f.fish();

                 3:编译通过,运行异常

                    1:ClassCastException

                 4:虽然是多态,但是鸟不能转为狗,狗不能转为鱼,他们之间没有关系。

    class Animal {
        String color;
    
        Animal() {
    
        }
    
        Animal(String color) {
            this.color = color;
        }
    
        void run() {
            System.out.println("跑跑");
        }
    }
    
    class Dog extends Animal {
        Dog() {
    
        }
    
        Dog(String color) {
            super(color);
        }
    
        void run() {
            System.out.println("狗儿跑跑");
        }
    
        void protectHome() {
            System.out.println("旺旺,看家");
        }
    }
    
    class Fish extends Animal {
        Fish() {
    
        }
    
        Fish(String color) {
            super(color);
        }
    
        void run() {
            System.out.println("鱼儿水中游");
        }
    
        void swim() {
            System.out.println("鱼儿游泳");
        }
    
    }
    
    class Demo15 {
    
        public static void main(String[] args) {
    
            Animal ani = new Dog();
            // ani.protectHome();
            // 正常转换
            Dog d = (Dog) ani;
            d.protectHome();
    
            // 多态例外
            Animal an = new Animal();
            // ClassCastException
            // Dog d=(Dog)an
    
            // 多态例外
            Animal dog = new Dog();
            // ClassCastException
            // Fish f = (Fish) dog;
    
        }
    }

    6:案例2

    1:定义一功能,接收用户传入动物,根据用于传入的具体动物,执行该动物特有的方法

       2:使用多态,方法形参,不能确定用户传入的是那种动物

       3:使用instanceof 关键字,判断具体是何种动物,

       4:类转换,执行该动物的特有方法。

    /*
     案例2
     1:定义一功能,接收用户传入动物,根据用于传入的具体动物,执行该动物特有的方法
     2:使用多态,方法形参,不能确定用户传入的是那种动物
     3:使用instanceof 关键字,判断具体是何种动物,
     4:类转换,执行该动物的特有方法。
     */
    class Animal {
        String color;
    
        Animal() {
    
        }
    
        Animal(String color) {
            this.color = color;
        }
    
        void run() {
            System.out.println("跑跑");
        }
    }
    
    class Dog extends Animal {
        Dog() {
    
        }
    
        Dog(String color) {
            super(color);
        }
    
        void run() {
            System.out.println("狗儿跑跑");
        }
    
        void protectHome() {
            System.out.println("旺旺,看家");
        }
    }
    
    class Fish extends Animal {
        Fish() {
    
        }
    
        Fish(String color) {
            super(color);
        }
    
        void run() {
            System.out.println("鱼儿水中游");
        }
    
        void swim() {
            System.out.println("鱼儿游泳");
        }
    
    }
    
    class Bird extends Animal {
        Bird() {
    
        }
    
        Bird(String color) {
            super(color);
        }
    
        void run() {
            System.out.println("鸟儿空中飞");
        }
    
        void fly() {
            System.out.println("我是一只小小鸟。。。。");
        }
    }
    
    class Demo16 {
    
        public static void main(String[] args) {
    
            System.out.println();
            doSomething(new Dog());
            doSomething(new Bird());
            doSomething(new Fish());
        }
    
        // 定义一功能,接收用户传入动物,根据用于传入的具体动物,执行该动物特有的方法
        public static void doSomething(Animal a) {
            if (a instanceof Dog) {
                Dog d = (Dog) a;
                d.protectHome();
            } else if (a instanceof Fish) {
                Fish f = (Fish) a;
                f.swim();
            } else if (a instanceof Bird) {
                Bird b = (Bird) a;
                b.fly();
            } else {
                System.out.println("over");
            }
        }
    }
    author@nohert
  • 相关阅读:
    【iOS开发每日小笔记(十二)】仿Facebook登录界面 错误提示抖动 利用CAAnimation设置动画效果
    《跑酷好基友》(英文名:BothLive)隐私政策声明
    【iOS开发每日小笔记(十一)】iOS8更新留下的“坑” NSAttributedString设置下划线 NSUnderlineStyleAttributeName 属性必须为NSNumber
    【iOS开发每日小笔记(十)】自制带圆框的头像 利用在CALayer设置“寄宿图”
    【iOS开发每日小笔记(九)】在子线程中使用runloop,正确操作NSTimer计时的注意点 三种可选方法
    2018/3/29
    2018/3/26
    2018/3/25
    BZOJ[3091] 城市旅行
    2018/3/23
  • 原文地址:https://www.cnblogs.com/gzgBlog/p/13585076.html
Copyright © 2020-2023  润新知