19、对象多态性

对象多态性

多态性依赖于方法覆写。

class A {
    public void print() {
        System.out.println("A中的方法");
    }
}

class B extends A {
    public void print() {
        System.out.println("覆写的方法");
    }
}

public class Demo {
    public static void main(String[] args) {
        B b = new B();
        b.print(); // 覆写的方法
    }
}

1、多态性分为两种:

(1)方法的多态性
	|- 方法重载:同一个方法名,根据传入的参数类型或个数的不同,执行不同方法体;
	|- 方法覆写:同一个方法,根据对象所属的子类不同,执行不同方法体。
(2)对象的多态性:指发生在具有继承关系的类中,父类与子类的转换。
	|- 向上转型(自动完成):父类 父类对象 = 子类实例化;
	|- 向下转型(强制完成):子类 子类对象 = (父类)父类实例化;

范例:向上转型

public class Demo {
    public static void main(String[] args) {
        A a = new B();
        a.print(); // 覆写的方法
    }
}

范例:向下转型

public class Demo {
    public static void main(String[] args) {
        B b = (B) new A(); // 向下转型
        b.print(); // 覆写的方法
    }
}

2、向上转型:由于子类对象都可以自动向上转型,所以可应用于参数的统一。

class A {
    public void print() {
        System.out.println("A中的方法");
    }
}

class B extends A {
    public void print() {
        System.out.println("B覆写的方法");
    }
}

class C extends A {
    public void print() {
        System.out.println("C覆写的方法");
    }
}

public class Demo {
    public static void main(String[] args) {
        A a1 = new B(); // 向上转型
        A a2 = new C(); // 向上转型
        a1.print(); // B覆写的方法
        a2.print(); // C覆写的方法
    }
}

a1,a2参数统一后,还可以调用子类覆写的方法,即同一个方法针对不同子类可以有不同实现。
3、向下转型:父类发生向上转型后,不能调用子类中自定义的方法。因此当父类要调用子类自定义方法时,需要进行向下转型,将父类对象变为子类对象。

class A {
}

class B extends A {
    public void fun() {
        System.out.println("自定义方法");
    }
}

public class Demo {
    public static void main(String[] args) {
        A a = new B(); // 向上转型
        a.fun(); // 报错,无法调用B自定义方法
    }
}

向下转型后,可以调用子类自定义的方法:

class A {
}

class B extends A {
    public void fun() {
        System.out.println("自定义方法");
    }
}

public class Demo {
    public static void main(String[] args) {
        A a = new B(); // 向上转型
        B b = (B) a; // 向下转型
        b.fun();
    }
}

问题:上述代码中不适用向下转型,直接实例化子类对象就可以直接调用fun(),为什么还要转型?
答:数据的操作分为两步:设置数据(最需要进行参数统一)和取出数据。

public class Demo {
    public static void main(String[] args) {
        fun(new B()); // 向上转型
    }
    public static void fun(A a){ // 统一参数
        B b = (B) a; // 向下转型
        b.fun(); // 调用子类自定义方法
    }
}

5、个性化操作在开发中尽量少出现,因为对象的强制转型容易带来安全隐患。

class A {
    public void print() {
        System.out.println("A.print()");
    }
}

class B extends A {
    public void print() {
        System.out.println("B.print()");
    }
}

public class Demo {
    public static void main(String[] args) {
        A a = new A();
        B b = (B) a;
        b.print();
    }
}

上述代码会报错,Exception in thread "main" java.lang.ClassCastException: A cannot be cast to B at ExDemo.main(ExDemo.java:15),表示类转换异常,指的是两个没有关系的类对象强制进行向下转型时发生的异常,因此向下转型存在风险。
为保证转型的安全性,Java提供关键字instanceof,其返回结果为boolean:对象 instanceof 类
如果某个对象是某个类的实例,则会返回true,反之返回false。

class A {
    public void print() {
        System.out.println("A.print()");
    }
}

class B extends A {
    public void print() {
        System.out.println("B.print()");
    }
}

public class Demo {
    public static void main(String[] args) {
        A a = new B();
        System.out.println(a instanceof A); // true
        System.out.println(a instanceof B); // true
        if (a instanceof B) {
            B b = (B) a;
            b.print(); // B.print()
        }
    }
}

向下转型前应先进行对象的向上转型,建立关系后才能进行向下转型。

总结:
(1)大多数情况只使用向上转型,使得参数统一,便于程序设计;子类尽量覆写方法,而不是自定义方法;
(2)极少情况使用向下转型调用子类的自定义方法,或者不转型。

你可能感兴趣的:(#,Java基础)