zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    数据绑定表达式语法(Eval,Bind区别)
    使用博客园的第一件事 自定义主题
    sql2000 跨服务器复制表数据
    使用UpdatePanel 局部刷新出现中文乱码的解决方法!!
    MMC不能打开文件MSC文件
    sql 日期 、时间相关
    loaded AS2 swf call function in AS3 holder
    Rewrite the master page form action attribute in asp.net 2.0
    100万个不重复的8位的随机数
    flash 中实现斜切变型
  • 原文地址:https://www.cnblogs.com/gzgBlog/p/13585076.html
Copyright © 2011-2022 走看看