天天看点

c 子类对象 访问父类对象受保护成员_面向对象三大特征: 多态

c 子类对象 访问父类对象受保护成员_面向对象三大特征: 多态

多态的概述和代码体现

什么是多态? 多态的前提是什么?
总结:
    1.多态: 事物存在的多种形态
            对象存在的多种形态
    (代码层面)对象存在的多种类型
        Cat c = new Cat();    //对象是 猫   类
        Animal a = new Cat(); //对象是 动物 类

    2.多态的前提: 
        ● 要有继承关系(extends)
        ● 要有[父类引用]指向[子类对象]    
              Animal a  =  new Cat();
        ● 有方法的重写(没有也可以多态形式创建对象)
           

多态的体现

多态体现的格式:

父类类型  变量名  =  new  子类对象 ;
变量名.方法名();
           
父类类型: 指子类对象继承的父类类型,或者实现的父接口类型

代码如下:

Fu f = new Zi();
f.method();
           

当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有则编译错误 如果有,执行的是子类重写后的方法

代码如下:

定义父类:

public abstract class Animal {
    public abstract void eat () ;
    }
           

定义子类:

class Cat extends Animal {
    public void eat (){
        System.out.println("吃鱼");
    }
}

class Dog extends Animal {
        public void eat (){
            System.out.println("吃骨头");
        }
    }
           

定义测试类:

public class Test {
    public static void main (String [] args) {
        Animal a1 = new Cat();
        a1.eat();

        Animal a2 = new Dog();
        a2.eat();
    }
}
           

多态的好处

实际开发的过程中,父类类型作为方法形式参数,传递子类对象给方法,进行方法的调用 ,更能体现出多态的拓展性与便利,代码如下:

定义父类:

public abstract class Animal{
    public abstract void eat();
}
           

定义子类:

class Cat extends Animal {
    public void eat() {
        System.out.println("吃鱼");
    }
}

class Dog extends Animals {
    public void eat() {
        System.out.println("吃骨头");
    }
}
           

定义测试类:

public class Test {
    public static void main(String[] args) {
    // 多态形式,创建对象
    Cat c = new Cat();
    Dog d = new Dog();
    // 调用showCatEat
    showCatEat(c);
    // 调用showDogEat
    showDogEat(d);
/*
以上两个方法, 均可以被showAnimalEat(Animal a)方法所替代
而执行效果一致
*/
    showAnimalEat(c);
    showAnimalEat(d);
}
    public static void showCatEat (Cat c){
    c.eat();
}
    public static void showDogEat (Dog d){
    d.eat();
}
    public static void showAnimalEat (Animal a){
    a.eat();
}
           

多态中成员访问特点

多态调用成员变量 多态调用成员方法 多态调用静态方法
总结:
    //多态创建对象,调用成员变量的特点: 
    1.编译看左边(父类),运行看左边(父类)
                //num 10  父类的值                 //num 20  子类的值
                Animal a = new Cat();
                System.out.println(a.num); // 10
          原因: 因为父类的类型,所以只能看到堆内存中super的一小块空间


    //多态创建对象,调用成员方法的特点
    2.编译看左边(父类),运行看右边(子类)
        编译时会检查父类中是否存在该方法[也叫动态绑定机制]

           如果不存在,编译阶段直接报错

           如果存在, 编译通过,但是运行时,执行子 类的方法(因为部分方法在父类中,是不存在方法体逻辑的如果运行时走父类的方法,那么没有逻辑就没有意义)
    //多态创建对象,调用静态方法的特点
    3.
           

多态的好处和弊端

总结:

好处:

1.提高了代码的复用性

2.提高了代码的维护性

3.提高了代码的扩展性:可以将一个方法的形式参数,定义为父亲类型,该方法就能接受这个父类的任意子类对象

多态:父类引用,指向子类对象

看一段代码理解一下

public class TestSuperMan{
    public static void main (String [] args) {
        //1. 超人乔装成人   
        Person p =new SuperMan();//向上转型(父类引用指向子类引用,此时不能调用子类的属性和行为)

        //多态创建对象,并调用成员变量的特点(编译看左边,运行看左边)
        System.out.println(p.name);// 克拉克
        //2.谈生意
        p.谈生意();

        //这时有人跳楼,超人要去救人,
        p.fly();  //报错,因为乔装成人了

        //多态的弊端:不能调用子类特有的属性和行为
        //需要向下转型,将乔装成人的[超人]-->转换为超人类型
        SuperMan sm = (SuperMan) p ;//向下转型

        //3.飞出去救人
        System.out.println(sm.name);
        sm.fly();
    }
}

class Person {
    String name = "克拉克";
    public void 谈生意 () {
        System.out.println("谈几个亿的大单子");
        }
    }

class SuperMan extends Person {        
    String name = "超人";
    public void fly () {
        System.out.println("飞出去救人"");
    }
}
           

再看一个案例

public class Demo {
    public static void main (String [] args) {
    Animal a = new Dog();
    Dog d = (Dog) a ; //不报错

    Cat c = (Cat) a ;//报错 ,狗类和猫类不存在子父类关系.ClassCastException :类型转换异常
    产生:当引用数据类型的强转,出现了错误就会抛出此异常

    向下转型注意:
        1. 向下转型,必须发生在子父类的关系当中
        2. 向下转型之前,必须得转上去,才能转下来 
        Animal a = new Animal();
        Dog d = (Dog) a ;//报错
    }

}

class Animal {}

class Dog extends Animal{}

class Cat extends Animal{}