03.Java 基础 - 多态

基本概念

多态是同一个行为具有多个不同表现形式或形态的能力。

多态性是对象多种表现形式的体现。

多态发生的条件 :继承、重写、向上转型

动态绑定是多态实现的具体形式。


实例探究

下面通过一个例子验证上面的概念。

// 车
class Car {
    public void show(){
        System.out.println("This is a car");
    }
}

//丰田
class Toyota extends Car{
    public void show(){
        System.out.println("This is a Japan car");
    }
}

//别克
class Buick extends Car{
    public void show(){
        System.out.println("This is a USA car");
    }
}

public class Test{  
    public static void main(String[] args) {
        Car c1 = new Toyota();
        Car c2 = new Buick();
        c1.show();
        c2.show();
        // 打印内容:
        // This is a Japan car
        // This is a USA car
    }
}

观察代码,在调用 Car 的 show 方法时打印了不同的内容,体现了类的多态性。同时例子也满足了发生多态的三个基本条件:

  • 继承:Toyota 、Buick 继承自 Car
  • 重写: Toyota 、Buick 重写了 Car 的 show 方法
  • 向上转型:创建 Toyota 、Buick 对象时发生向上转型

再来看来一个典型题目:

class A {

    public String show(A obj) {
        return ("A and A");
    }

    public String show(D obj) {
        return ("A and D");
    }
}

class B extends A {

    public String show(A obj) {
        return ("B and A");
    }

    public String show(B obj) {
        return ("B and B");
    }
}

class C extends B {
}

class D extends B {
}

public class Test {
    public static void main(String[] args) {
        A a1 = new A();
        A a2 = new B();
        B b = new B();
        C c = new C();
        D d = new D();

        // 1.因此 B 是 A 的子类,调用类 A 的 show(A obj) 方法,输出:A and A
        System.out.println(a1.show(b));

        // 2.因为 C 是 A 的子类,调用类 A 的 show(A obj) 方法,输出:A and A
        System.out.println(a1.show(c));

        // 3.调用类 A 的 show(D obj) 方法,输出:A and D
        System.out.println(a1.show(d));

        // 4.因为 B 向上转型成 A, 且 B 是 A 的子类,调用类 A 的 show(A obj) 方法
        // 但是由于 B 中重写了 show(A obj) 方法,导致运行期间发生的动态绑定,调用 类 B 的 show(A obj) 方法
        // ,输出:B and A
        System.out.println(a2.show(b));

        // 5.同上
        System.out.println(a2.show(c));

        // 6.B 向上转型成 A,默认调用类 A 的 show(D obj) 方法,输出:A and D
        System.out.println(a2.show(d));

        // 7.调用类 B 的 show(B obj) 方法,输出:B and B
        System.out.println(b.show(b));

        // 8.C 是 B 的子类,调用类 B 的 show(B obj) 方法,输出:B and B
        System.out.println(b.show(c));

        // 9.调用继承自类 A 的 show(D obj) 方法,输出:A and D
        System.out.println(b.show(d));

    }
}

构造器与多态

同样的通过一个实例来探究

class Parent {
    void print() {
        System.out.println("I am a Parent");
    }

    Parent() {
        print();
    }
}

class Son extends Parent {
    int num = 1;

    // 重写(override)了父类方法
    void print() {
        System.out.println("I am a Son " + num);
    }

    Son() {
        print();
    }
}

public class Test {
    public static void main(String[] args) {
        Son son = new Son();
        /**
         * 输出内容: 
         * I am a Son 0
         * I am a Son 1
         */
    }
}

通过输出内容我们可以看到,Parent 的构造器由于动态绑定,调用了 Son 的 print(),由于 num 还未被初始化,导致了值为 0。

基本概念

多态是同一个行为具有多个不同表现形式或形态的能力。

多态性是对象多种表现形式的体现。

多态发生的条件 :继承、重写、向上转型

动态绑定是多态实现的具体形式。


实例探究

下面通过一个例子验证上面的概念。

// 车
class Car {
    public void show(){
        System.out.println("This is a car");
    }
}

//丰田
class Toyota extends Car{
    public void show(){
        System.out.println("This is a Japan car");
    }
}

//别克
class Buick extends Car{
    public void show(){
        System.out.println("This is a USA car");
    }
}

public class Test{  
    public static void main(String[] args) {
        Car c1 = new Toyota();
        Car c2 = new Buick();
        c1.show();
        c2.show();
        // 打印内容:
        // This is a Japan car
        // This is a USA car
    }
}

观察代码,在调用 Car 的 show 方法时打印了不同的内容,体现了类的多态性。同时例子也满足了发生多态的三个基本条件:

  • 继承:Toyota 、Buick 继承自 Car
  • 重写: Toyota 、Buick 重写了 Car 的 show 方法
  • 向上转型:创建 Toyota 、Buick 对象时发生向上转型

再来看来一个典型题目:

class A {

    public String show(A obj) {
        return ("A and A");
    }

    public String show(D obj) {
        return ("A and D");
    }
}

class B extends A {

    public String show(A obj) {
        return ("B and A");
    }

    public String show(B obj) {
        return ("B and B");
    }
}

class C extends B {
}

class D extends B {
}

public class Test {
    public static void main(String[] args) {
        A a1 = new A();
        A a2 = new B();
        B b = new B();
        C c = new C();
        D d = new D();

        // 1.因此 B 是 A 的子类,调用类 A 的 show(A obj) 方法,输出:A and A
        System.out.println(a1.show(b));

        // 2.因为 C 是 A 的子类,调用类 A 的 show(A obj) 方法,输出:A and A
        System.out.println(a1.show(c));

        // 3.调用类 A 的 show(D obj) 方法,输出:A and D
        System.out.println(a1.show(d));

        // 4.因为 B 向上转型成 A,应该是调用类 A 的 show(A obj) 方法
        // 由于 B 中重写了 show(A obj) 方法,实际调用 类 B 的方法,,输出:B and A
        System.out.println(a2.show(b));

        // 5.同上
        System.out.println(a2.show(c));

        // 6.B 向上转型成 A,默认调用类 A 的 show(D obj) 方法,输出:A and D
        System.out.println(a2.show(d));

        // 7.调用类 B 的 show(B obj) 方法,输出:B and B
        System.out.println(b.show(b));

        // 8.C 是 B 的子类,调用类 B 的 show(B obj) 方法,输出:B and B
        System.out.println(b.show(c));

        // 9.调用继承自类 A 的 show(D obj) 方法,输出:A and D
        System.out.println(b.show(d));

    }
}

构造器与多态

同样的通过一个实例来探究

class Parent {
    void print() {
        System.out.println("I am a Parent");
    }

    Parent() {
        print();
    }
}

class Son extends Parent {
    int num = 1;

    // 关键 -> 重写了父类的方法
    void print() {
        System.out.println("I am a Son " + num);
    }

    Son() {
        print();
    }
}

public class Test {
    public static void main(String[] args) {
        Son son = new Son();
        // 输出内容: 
        // I am a Son 0
        // I am a Son 1
    }
}

分析结果,其实它涉及到了三个内容:

  • Son 在实例化的过程中,Parent 的构造函数, Parent 的构造函数先执行。
  • Son 重写了 print 方法,因此 Parent 调用的是 Son 重写后的方法。
  • 在 Parent 由于 num 还未被初始化,因此值为 0。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

oxf

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值