面向对象三大特征-多态

多态

有一个用来判断是否应该设计为继承关系的简单规则,这就是”is a”规则,它表明子类的每个对象也是超类的对象.
例如:每个经理都是员工,因此,将Manager类设计为Employee类的子类是显而易见的,反之不然,并不是没一名员工都是经理.

“is a” 规则的另一种表书法是置换法则,它表明程序中出现超类对象的任何地方都可以用子类对象置换.

在java程序设计语言中,对象变量时多态的.一个Employee变量既可以引用一个Employee对象,也可以引用一个Employee类的任何一个子类的对象(例如:Manager,Executive,Secretary等)

多态:一个对象具备多种形态。(父类的引用类型变量指向了子类的对象) 或者是接口 的引用类型变量指向了接口实现类的对象)

多态的前提:必须存在继承或者实现 关系。

动物  a  = new   狗();
//动物类
abstract class Animal{

    String name;

    String  color = "动物色";

    public Animal(String name){
        this.name = name;
    }

    public abstract void run();

    public static void eat(){
        System.out.println("动物在吃..");
    }

}

//老鼠
class  Mouse extends Animal{

    String color = "黑色";

    public Mouse(String name){
        super(name);
    }

    public  void run(){
        System.out.println(name+"四条腿慢慢的走!");
    }

    public static void eat(){
        System.out.println("老鼠在偷吃..");
    }

    //老鼠特有方法---打洞
    public void dig(){
        System.out.println("老鼠在打洞..");
    }
}



class Fish extends Animal {

    public Fish(String name){
        super(name);
    }


    public  void run(){
        System.out.println(name+"摇摇尾巴游..");
    }
}


class Demo11 
{
    public static void main(String[] args) 
    {
        /*
        Mouse m = new Mouse("老鼠");
        System.out.println(m.color);

        //多态: 父类的引用类型变量指向子类的对象
        */
        Animal a = new Mouse("老鼠");
        a.dig();
        //a.eat();
    }   
}

多态要注意 的细节:

1.  多态情况下,子父类存在同名的成员变量时,访问的是父类的成员变量。
2.  多态情况下,子父类存在同名的非静态的成员函数时,访问的是子类的成员函数。
3.  多态情况下,子父类存在同名的静态的成员函数时,访问的是父类的成员函数。
4.  多态情况下,不能访问子类特有的成员。

总结:多态情况下,子父类存在同名的成员时,访问的都是父类的成员,除了在同名非静态函数时才是访问子类的。

多态的特点

1:编译时期,参考引用型变量所属的类是否有调用的方法,如果有编译通过。没有编译失败
2:运行时期,参考对象所属类中是否有调用的方法。
3:总之成员函数在多态调用时,编译看左边,运行看右边。

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

多态的应用:

1.多态用于形参类型的时候,可以接收更多类型的数据 。
2. 多态用于返回值类型的时候,可以返回更多类型的数据。

多态的好处: 提高了代码的拓展性。

需求1: 定义一个函数可以接收任意类型的图形对象,并且打印图形面积与周长。

//图形类
abstract class MyShape{

    public abstract void getArea();

    public abstract void getLength();   
}



class Circle extends MyShape{

    public static final double PI = 3.14;

    double r;

    public Circle(double r){
        this.r =r ; 
    }

    public  void getArea(){
        System.out.println("圆形的面积:"+ PI*r*r);
    }

    public  void getLength(){
        System.out.println("圆形的周长:"+ 2*PI*r);
    }
}


class Rect  extends MyShape{

    int width;

    int height;

    public Rect(int width , int height){
        this.width = width;
        this.height = height;
    }

    public  void getArea(){
        System.out.println("矩形的面积:"+ width*height);
    }

    public  void getLength(){
        System.out.println("矩形的周长:"+ 2*(width+height));
    }
}



class Demo12 {

    public static void main(String[] args) 
    {
        /*
        //System.out.println("Hello World!");
        Circle c = new Circle(4.0);
        print(c);

        Rect r = new Rect(3,4);
        print(r);
        */

        MyShape m = getShape(0); //调用了使用多态的方法,定义的变量类型要与返回值类型一致。
        m.getArea();
        m.getLength();


    }


    //需求1: 定义一个函数可以接收任意类型的图形对象,并且打印图形面积与周长。
    public static void print(MyShape s){ // MyShpe s = new Circle(4.0);
        s.getArea();
        s.getLength();
    }


    // 需求2: 定义一个函数可以返回任意类型的图形对象。
    public static MyShape  getShape(int i){
        if (i==0){
            return new Circle(4.0);
        }else{
            return new Rect(3,4);
        }
    }


}

多态之类型转型

案例定义Father类

1:定义method1和method2方法
2:定义Son类继承Father类
    定义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();
    }
}

猜你喜欢

转载自blog.csdn.net/qq847540343/article/details/78238906