Java 多态的理解

面向对象编程有三个特征,即封装、继承和多态。

  封装隐藏了类的内部实现机制,从而可以在不影响使用者的前提下改变类的内部结构,同时保护了数据。

  继承是为了重用父类代码,同时为实现多态性作准备。那么什么是多态呢?

要理解多态性,首先要知道什么是“向上转型”。

  我定义了一个子类Cat,它继承了Animal类,那么后者就是前者是父类。我可以通过

  Cat c = new Cat();

  实例化一个Cat的对象,这个不难理解。但当我这样定义时:

  Animal a = new Cat();

  这代表什么意思呢?

  很简单,它表示我定义了一个Animal类型的引用,指向新建的Cat类型的对象由于Cat是继承自它的父类Animal,所以Animal类型的引用是可以指向Cat类型的对象的。那么这样做有什么意义呢?因为子类是对父类的一个改进和扩充,所以一般子类在功能上较父类更强大,属性较父类更独特,

  定义一个父类类型的引用指向一个子类的对象既可以使用子类强大的功能,又可以抽取父类的共性。

  所以,父类类型的引用可以调用父类中定义的所有属性和方法,而对于子类中定义而父类中没有的方法,它是不能调用的;(但是如果强制把超类转换成子类的话,就可以调用子类中新添加而超类没有的方法了。

  同时,父类中的一个方法只有在在父类中定义而在子类中没有重写的情况下,才可以被父类类型的引用调用;

换个说法 : 如果子类重写了父类的定义的方法,父类类型的引用调用的则是子类的方法 这就是动态连接。

 例子

class Father {
	void fun1(){
		fun2();
	}
	void fun2(){
	}
}

class Child extends Father {
	void fun1(int i){
		System.out.println("func1 in Child");
	}

	void fun2(){
		System.out.println("func2 in Child");
	}
}

public class Main {
    public static void main(String[] args) {
        Father child = new Child();
        child.fun1();
}

结果是显示 func2 in Child

解析

因为 类Child 没有重写了 类Father 的 fun1(),所以会调用父类的 fun1()。而在 父类的 fun1() 中,会调用子类的 fun2(),这是因为子类重写了 fun2(),将父类的 fun2() “屏蔽”掉了。

解析对应上文红字部分


例二:

class 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");
	}

	public String show() {// 重写父类的函数
		return ("show in Class B");
	}
}

class C extends B {
}

class D extends B {
}


public class Main {
    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(a1.show(b));
        System.out.println(a1.show(c));
        System.out.println(a1.show(d));
        System.out.println("********************");
        System.out.println(a2.show(b));
        System.out.println(((B) a2).show(b));
        System.out.println(a2.show(c));
        System.out.println(a2.show(d));
        System.out.println("********************");
        System.out.println(b.show(b)); 
        System.out.println(b.show(c)); 
        System.out.println(b.show(d));
    }
}

结果如下

分析:

部分摘自http://blog.youkuaiyun.com/thinkGhoster/article/details/2307001

方法调用的优先问题 ,优先级由高到低依次为:this.show(O)、super.show(O)、this.show((super)O)、super.show((super)O)。让我们来看看它是怎么工作的。


a1 是 A 的一个对象引用,调用 类 A 的show() 会根据传入的参数 ,函数会发生重载。若传入 D的实例,则会显示 “ A AND D” .若传入 A 的实例,或者 A 的子类的

实例,则会输出 “A AND A ”.


a2 是 A 的一个引用,却指向一个 B 的对象(B 是 A 的子类)。a2 调用 show()时,先会看父类中有无该函数,该函数如果没有被子类重写,则执行父类的函数,否则执行子类的函数。

a2.show(b)   ,类 A 中存在该函数 show(A a),但是 在子类 B 中被重写了,故 执行 类B 的 show(A   a)。输出  B AND A. 下面以方法调用顺序说明

a2 对应 this 应该为 A, O 对应b. (super)O 就是对应 A.

a2.show(b)  类 A 中 没有show(B b),====》类A没有super=======>A.show((super)O)  即 A.show(A a)  但是发现类B 重写了该方法,故执行 B.show(A a).


a2.show(c)

a2 对应 this 应该为 A, O 对应c. (super)O 就是对应 B.

a2.show(c)  类 A 中 没有show(C c),====》类A没有super=======>A.show((super)O)  即 A.show(B b)  刚刚我们知道 A.show(B b)显示   B AND A.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值