Java面向对象——多态(下)

向下转型

与向上转型相对应的就是向下转型了。向下转型是把父类对象转为子类对象。

向下转型注意事项

  • 向下转型的前提是父类对象指向的是子类对象(也就是说,在向下转型之前,它得先向上转型)
  • 向下转型只能转型为本类对象

案例:

lass A {
    public String show(D obj) {
        return ("A and D");
    }
 
    public String show(A obj) {
        return ("A and A");
    }
 
}
 
class B extends A{
    public String show(B obj){
        return ("B and B");
    }
 
    public String show(A obj){
        return ("B and A");
    }
}
 
class C extends B{
 
}
 
class D extends B{
 
}
 
public class Demo {
    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();
 
        System.out.println("1--" + a1.show(b));
        System.out.println("2--" + a1.show(c));
        System.out.println("3--" + a1.show(d));
        System.out.println("4--" + a2.show(b));
        System.out.println("5--" + a2.show(c));
        System.out.println("6--" + a2.show(d));
        System.out.println("7--" + b.show(b));
        System.out.println("8--" + b.show(c));
        System.out.println("9--" + b.show(d));
    }
}

当父类对象引用变量引用子类对象时,被引用对象的类型决定了调用谁的成员方法,引用变量类型决定可调用的方法。如果子类中没有覆盖该方法,那么会去父类中寻找。

实例

class X {
    public void show(Y y){
        System.out.println("x and y");
    }
 
    public void show(){
        System.out.println("only x");
    }
}
 
class Y extends X {
    public void show(Y y){
        System.out.println("y and y");
    }
    public void show(int i){
 
    }
}
 
class main{
    public static void main(String[] args) {
        X x = new Y();
        x.show(new Y());
        x.show();
    }
}

Y 继承了 X,覆盖了 X 中的 show(Y y) 方法,但是没有覆盖 show() 方法。

这个时候,引用类型为X的 x 指向的对象为 Y,这个时候,调用的方法由 Y 决定,会先从 Y 中寻找。执行 x.show(new Y());,该方法在 Y 中定义了,所以执行的是 Y 里面的方法;

但是执行 x.show(); 的时候,有的人会说,Y 中没有这个方法啊?它好像是去父类中找该方法了,因为调用了 X 中的方法。

事实上,Y 类中是有 show() 方法的,这个方法继承自 X,只不过没有覆盖该方法,所以没有在 Y 中明确写出来而已,看起来像是调用了 X 中的方法,实际上调用的还是 Y 中的。

这个时候再看上面那句难理解的话就不难理解了吧。X是引用变量类型,它决定哪些方法可以调用;show()和 show(Y y) 可以调用,而 show(int i)不可以调用。Y 是被引用对象的类型,它决定了调用谁的方法:调用 y 的方法。

上面的是一个简单的知识,它还不足以让我们理解那个复杂的例子。我们再来看这样一个知识:

继承链中对象方法的调用的优先级:this.show(O)、super.show(O)、this.show((super)O)、super.show((super)O)。

如果你能理解这个调用关系,那么多态你就掌握了。我们回到那个复杂的例子:

abcd 的关系是这样的:C/D —> B —> A

我们先来分析4 : a2.show(b)

  • 首先,a2是类型为A的引用类型,它指向类型为B的对象。A确定可调用的方法:show(D obj)和show(A obj)。
  • a2.show(b) ==> this.show(b),这里this指的是B。
  • 然后.在B类中找show(B obj),找到了,可惜没用,因为show(B obj)方法不在可调用范围内,this.show(O)失败,进入下一级别:super.show(O),super指的是A。
  • 在A 中寻找show(B obj),失败,因为没用定义这个方法。进入第三级别:this.show((super)O),this指的是B。
  • 在B中找show((A)O),找到了:show(A obj),选择调用该方法。
  • 输出:B and A
  • 首先,b为类型为B的引用对象,指向类型为B的对象。没有涉及向上转型,只会调用本类中的方法。
  • 在B中寻找show(D obj),方法。现在你不会说没找到了吧?找到了,直接调用该方法。
  • 输出 A and D。

总结

  1. 多态,简而言之就是同一个行为具有多个不同表现形式或形态的能力。
  2. 多态的分类:运行时多态和编译时多态。
  3. 运行时多态的前提:继承(实现),重写,向上转型
  4. 向上转型与向下转型。
  5. 继承链中对象方法的调用的优先级:this.show(O)、super.show(O)、this.show((super)O)、super.show((super)O)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值