浅谈个人对Java多态性的理解

对于Java的多态性,很多人难以理解,起初我也一样,最近有点点琢磨出来了其中的原理,在此跟大家分享,例子代码也不复杂,相信看完或多或少会有点收获。

多态性可以理解为:给对象一个激励,让对象自行决定应该做出何种响应。(在网上看到的一句话,个人觉得对多态性的概括很全面,个人对多态性的理解也是用这句话来概括。)

刚开始理解这句话可能有点难下面来看例子具体分析。

Java的多态性表现形式有两种,函数重载(overload)和函数覆盖(override,也就是函数重写)。现在理解不了没事,来看例子。

首先:

//多态性之函数(方法)重载
package com.polymorphism;

public class TestPolymorphism{
	//函数1
	private void dosomething() {
		System.out.println("我是无行参函数");
	}
	//函数2
	private void dosomething(int a) {
		System.out.println("我是形参为int类型的函数:"+a);
	}
	//函数3
	private void dosomething(String str) {
		System.out.println("我是形参为String类型的函数:"+str);
	}
	//函数4
	private void dosomething(int a,String str) {
		System.out.println("我是形参为int和String类型的函数:"+a+" "+str);
	}
	//函数5
	private void dosomething(String str,int a) {
		System.out.println("我是形参为String和int类型的函数:"+str+" "+a);
	}
	public static void main(String[] args) {
		TestPolymorphism p=new TestPolymorphism();
		p.dosomething();//第一次调用
		p.dosomething(10);//第二次调用
		p.dosomething("hello");//第三次调用
		p.dosomething(10, "hello");//第四次调用
		p.dosomething("hello", 10);//第五次调用
	}
}

结果:

我是无行参函数
我是形参为int类型的函数:10
我是形参为String类型的函数:hello
我是形参为int和String类型的函数:10 hello
我是形参为String和int类型的函数:hello 10


对于这个TestPolymorphism类,函数也很简单,只不过大家会看到,所有的函数都是同名的,都是dosomething(),那么如果在主函数调用这个函数的话,他怎么知道去调用哪一个呢?然而大家再看看每个函数,是不是有不同的地方呢?如形参个数、形参类型什么的。对,每个函数都跟其他的不一样。在Java中,同一个类里面写多个函数名相同,但是形参类型、个数以及顺序至少有一个不同的函数,就叫做函数重载。如果两个函数一摸一样,那就会出错。

那么,来看主方法的调用,(虽然p是一个TestPolymorphism类的引用,指向这个类的一个对象,但习惯上的叫法就叫p对象)先创建p这个对象。

第一次调用,这个dosomething()没有实参,所以p只会找到没有形参的函数,也就是第一个函数然后执行,而不会去执行后面的2、3、4、5函数。

第二次调用,这个dosomething()传入了一个int类型的实参10,所以p会找到形参为int类型的函数,也就是第二个函数去执行。

第三次调用,这个dosomething()传入了一个String类型的实参“hello”字符串,所以p会找到形参为String类型的函数,也就是第三个函数去执行。

后面的两个函数调用是类似的情况。

现在再回顾那句话:给对象一个激励,让对象自行决定应该做出何种响应。是不是有一定的体会呢?给p对象一个激励,可以理解为函数的传入实参吧,响应就相当于p对象根据传入的实参去决定执行哪个函数,实现函数体。

PS:函数重写中,虽然可以使两个函数的返回值不同,但是这不足以区分两个方法的重载关系,所以必须通过形参的类型、个数及顺序来构成重载关系。

也许很多人会问,为什么要把函数写成同名的呢,写成不同的名字就不需要这么麻烦了呢?

其实不然,Java中很多时候需要用很多同名的函数,最简单的比如要通过不同的方式来实例化对象,而构造函数名都是相同的,所以这就需要函数重载了。


其次:

//多态性之函数(方法)覆盖(重写)
package com.polymorphism;
class Father{
	protected void dosomething(){
		System.out.println("我是Father的dosomething方法");
	}
}
class Son extends Father{
	protected void dosomething(){
		System.out.println("我是Son的dosomething方法");
	}
}
class Daughter extends Father{
	protected void dosomething(){
		System.out.println("我是Daughter的dosomething方法");
	}
}
public class TestPolymorphism{
	public static void main(String[] args) {
		Father f=new Father();
		f.dosomething();//调用1
		
		Father x=new Son();
		x.dosomething();//调用4
		
		Father y=new Daughter();
		y.dosomething();//调用5
	}
}


结果:

我是Father的dosomething方法
我是Son的dosomething方法
我是Daughter的dosomething方法


类的继承不多讲了,要注意的是子类不能继承父类private属性的变量和函数。

重写:多个子类都需要继承父类的某个方法,如果在每个子类中写一次这个方法,那么就会出现很多次重复的代码,那么会出现代码冗余的现象,所以把这个方法写在父类中,每个子类都继承这个方法,就避免了大量重复代码。但是一般在父类中的方法都是抽象方法,不能实现特定的功能,比如吃东西这个方法eat(),他只是实现吃东西这个动作,并不能实现吃什么东西。那么我要在子类中实现吃饭这个方法,就必须重写eat()方法来实现吃饭这个动作。再比如父类定义了一个画图形的方法draw(),子类要实现画三角形的功能,画三角形也是画图形,也就是说子类的draw()方法本来就有画图形的功能,你只要再写出指定画三角形的代码就行。。也就是说重写其实就是子类重新实现父类某个方法的功能,子类的重写的方法必须跟父类的方法一样(返回值类型、形参类型、形参个数、形参顺序等),但函数体应当不同。

理解了这个,重写就差不多了。

来看例子,很简单。Son和Daughter类都继承Father类并重写了其中的dosomething方法。

调用1都相信大家都能理解,每个对象直接调用自己的方法。

如果把父类引用指向子类对象,也就是x引用,再调用x对象里面的dosomething方法,那这个对象就实现子类的dosomething方法,也就是实现子类所重写的dosomething方法。而不是父类的dosomething方法。对于y引用是一样的。

这也是相当于给对象引用一个激励,让他自己决定去响应哪个激励。给对象引用(父类引用)的激励相当于不同的对象(父类对象或子类对象),响应相当于去执行哪个方法(父类还是子类的方法)。


现在应该能理解了多态性:给对象一个激励,让他自己决定去做出何种响应。

多态性的表现形式:

①同一个类之间:函数重载(overload)

②父类和子类之间:函数覆盖(override)


PS:本人第一次写博文,有什么缺陷或者写的有问题的地方欢迎指点,本人也是菜鸟一只,只是想跟大家共同进步,谢谢!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值