Java面向对象之多态性

系列文章目录

最近在学Java,学到了面向对象这一章节,面向对象有三大特性:封装性、继承性、多态性,其中最难理解的就是多态性了,我也在网上查了很多资料,有许多都是只说了多态性中一些特性而已,为了我能巩固这些知识、同时也可以为大家参考,所以我写下这一篇详解。



多态认识

多态是同一个行为具有多个不同表现形式或形态的能力。翻译过来就是说一个物体具有多种形态,多态就是不同对象对同一物体或事件发出不同的反应或响应。比如说人,人分男人,女人,这就是人这一个物体的多态,再比如说动物,动物有老虎、兔子和鸡等等。


一、多态的前提

1、要有继承关系

继承关系是多态的必要条件,就好像说现在有三个类,人的类,男人的类,女人的类,人这一个类它有走路、说话的方法,然后另外一个男人的类继承人这个类,它就拥有走路、说话的方法,然后男人大声的说话,再来一个女人的类,也继承人这个类,它也拥有走路、说话的方法,然后女人细声细语的说话,这样子人就有了两个形态,大声说话的男人,细声细语说话的女人。

2、要有方法重写

继续说上面的例子,男人虽然继承了人这个类的走路、说话的方法,但是在男人的类中,把说话的方法改为了大声的说话,女人的类中,把说话的方法改为了细声细语的说话,这就是使得不同的形态有着不同的特征。

这里要理解重写和重载的区别:
可以参考:https://blog.csdn.net/qq_42014192/article/details/89707483?spm=1001.2101.3001.6650.3&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-3-89707483-blog-124175633.pc_relevant_aa&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-3-89707483-blog-124175633.pc_relevant_aa

3、父类的引用指向子类的对象

上面的例子中,人的类是父类,男人的类和女人的类是子类,在创建多态的时候,要用父类的引用指向子类的对象。(这里看不懂没事,先继续往下看,下面会继续解释的)

Person p = new Woman();//Person是父类,Woman是女人的类。

多态前提的关系图

二、多态的特性与例子

1.多态绑定

代码如下(示例):

public class Person {//人的类
	String name = "Person";
	
	public void say(){
		System.out.println("person say");
	}
	
	public void show(){
		System.out.println("person show");
	}
}

public class Woman extends Person {//女人的类
	String name = "Woman";
	@Override
	public void say(){
		System.out.println("woman say");
	}
	@Override
	public void show(){
		System.out.println("woman show");
	}
	
	public void buy(){
		System.out.println("buy buy ...");
	}
}

public class Test {
	public static void main(String[] args) {
		// 多态的前提:1、要有继承关系 	2、要有方法重写	3、父类的引用指向子类的对象
		// 多态绑定
		Person p = new Woman();
		// 虚拟方法调用-编译看左边,运行看右边
		p.say();
		p.show();
//		p.buy(); //编译错误,编译看左边。buy为Woman的方法,Person不能调用
	}
}

注释中的==“虚拟方法调用-编译看左边,运行看右边”,在这里详细的说,它的意思就是向上转型,向上转型是什么呢?在上面我们说了子类会对父类中的一些方法进行重写,然后调用方法时就会调用子类重写的方法而不是原本父类的方法。向上转型后,子类单独定义的方法会丢失(即子类重载了父类中的方法),而子类中重写了父类的方法,当我们调用他们时,会调用重写的方法。
看上面的代码,Person类指向了Woman类,就是解释为这个人是女人,它就会调用女人类中的say()方法和show()方法,而不是Person类中的say()方法和show()方法。也就是上一段说的
向上转型后,子类单独定义的方法会丢失(即子类重载了父类中的方法),而子类中重写了父类的方法,当我们调用他们时,会调用重写的方法。==
在这里插入图片描述
再展开说,如果说在Woman类中没有重写say()方法和show()方法,那它就会调用Person中的say()方法和show()方法。

public class Person {//人的类
	String name = "Person";
	
	public void say(){
		System.out.println("person say");
	}
	
	public void show(){
		System.out.println("person show");
	}
}

public class Woman extends Person {//女人的类
	String name = "Woman";
//	@Override
//	public void say(){
//		System.out.println("woman say");
//	}
//	@Override
//	public void show(){
//		System.out.println("woman show");
//	}
	
	public void buy(){
		System.out.println("buy buy ...");
	}
}

public class Test {
	public static void main(String[] args) {
		// 多态的前提:1、要有继承关系 	2、要有方法重写	3、父类的引用指向子类的对象
		// 多态绑定
		Person p = new Woman();
		// 虚拟方法调用-编译看左边,运行看右边
		p.say();
		p.show();
//		p.buy(); //编译错误,编译看左边。buy为Woman的方法,Person不能调用
	}
}

在这里插入图片描述
从代码中看出有一句

//		p.buy(); //编译错误,编译看左边。buy为Woman的方法,Person不能调用

解释这一句还得回到 注释中的==“虚拟方法调用-编译看左边,运行看右边”==,编译看左边,我们多态绑定的时候,左边是Person类,buy()的方法是Woman中的,所以不能调用bug()方法。那我们怎么样才能调用呢?继续看下去。

		// 多态绑定
		Person p = new Woman();

2.调用子类特有的方法(向下转型)

代码如下(示例):

public class Person {//人的类
	String name = "Person";
	
	public void say(){
		System.out.println("person say");
	}
	
	public void show(){
		System.out.println("person show");
	}
}

public class Woman extends Person {//女人的类
	String name = "Woman";
	@Override
	public void say(){
		System.out.println("woman say");
	}
	@Override
	public void show(){
		System.out.println("woman show");
	}
	
	public void buy(){
		System.out.println("buy buy ...");
	}
}

public class Test {
	public static void main(String[] args) {
		// 多态的前提:1、要有继承关系 	2、要有方法重写	3、父类的引用指向子类的对象
		// 多态绑定
		Person p = new Woman();
		// 虚拟方法调用-编译看左边,运行看右边
		p.say();
		p.show();
//		p.buy(); //编译错误,编译看左边。buy为Woman的方法,Person不能调用
		System.out.println("类型没转化之前的属性:"+p.name);
		// 想调用buy的方法,要进行强制类型转换
		// 向下转型的方式
		Woman w = (Woman)p;//注意:p指向的对象必须是Woman的对象才可以这么做
		w.buy();
		System.out.println("类型转化之后的属性:"+w.name);
	}
}

还是上面的例子,我们要想调用Woman中的buy()方法,那我们要向下转型:

		// 想调用buy的方法,要进行强制类型转换
		// 向下转型的方式
		Woman w = (Woman)p;

注意:p指向的对象必须是Woman的对象才可以这么做
就是说刚才p是指向Woman类,那我们只能向下转向Woman类,不能转向Man类,如果转向Man类就会编译报错。

	Man m = (Man)p; // 发生错误:ClassCastException-类型转换异常

3、instanceof 判断

那么我们有没有什么方法来避免这样子的错误呢?有,为了解决类型转换异常,可以在向下转型时使用instanceof

a instanceof Woman: a对象是否是Woman的一个实例(对象),如果是返回true,否则返回false
	// 多态绑定
	Person p = new Woman();
	if(p instanceof Man){
			System.out.println("This is a Man");
		}else if(p instanceof Woman){
			System.out.println("This is a Waman");
		}
	System.out.println(p instanceof Person);//true
	System.out.println(p instanceof Woman);//true
	System.out.println(p instanceof Man);//false

在这里插入图片描述

如果说Person继承了另外一个类,那么p是哪几个对象的实例呢?
不想看下面的代码,那就看下面的图,是代码的继承关系:
在这里插入图片描述

public class Ceature {
	public void say(){
		System.out.println("Ceature say");
	}
	
	public void show(){
		System.out.println("Ceature show");
	}
}

public class Person extends Ceature {
	String name = "Person";
	
	public void say(){
		System.out.println("person say");
	}
	
	public void show(){
		System.out.println("person show");
	}
}
public class Woman extends Person {
	String name = "Woman";
	@Override
	public void say(){
		System.out.println("woman say");
	}
	@Override
	public void show(){
		System.out.println("woman show");
	}
	
	public void buy(){
		System.out.println("buy buy ...");
	}
}
public class Test {
	public static void main(String[] args) {
		Ceature c = new Ceature();
		System.out.println(c instanceof Ceature);//true
		System.out.println(c instanceof Person);//false
		System.out.println(c instanceof Woman);//false
		System.out.println(c instanceof Man);//false
	}
}

在这里插入图片描述
结合上面的例子可以看出c指向的对象 instanceof 对象所在的类及父类:true,c指向的对象instanceof 对象所在的类的子类:false
在这里插入图片描述

4、多态的其他向下转型

代码与上面一样,现在实例例子不一样

		Ceature cea = new Woman();
		Person per = (Person)cea;
		per.say();
		//per.buy();//报错
		Woman woman = (Woman)cea;
		woman.buy();

在这里插入图片描述
这里cea指明是女人,所以per向下转型为Person时,还是指明为女人,不能说向下转型之后,女人就变了吧,所以这里还是女人的形态,但是它不具有女人的特有的方法,好比如就不能调用Woman类中的buy()方法,因为它已经转型为Person类了,Person中没有buy()的方法,但是其他特征还是女人的特征。
(不能理解上面的意思,就这样子理解,向下转型成Person类了,如果Woman中有重写Person中的方法,那就调用的是Woman中重写的方法,没有重写就是调用自己的方法,但是Woman特有的不能调用,还需要继续向下转型成Woman类才能调用,就可以理解为向上转型吧。)

5、转型总结

多态的转型分为向上转型和向下转型两种。

向上转型:多态本身就是向上转型过的过程

使用格式:父类类型 变量名=new 子类类型();

适用场景:当不需要面对子类类型时,通过提高扩展性,或者使用父类的 功能就能完成相应的操作。

向下转型:一个已经向上转型的子类对象可以使用强制类型转换的格式,将父类引用类型转为子类引用各类型

使用格式:子类类型 变量名=(子类类型) 父类类型的变量;

适用场景:当要使用子类特有功能时。


总结

上面就是多态的一些重点内容了,多态是面向对象特性中最难理解的一个特性,所以在学习的时候要多下功夫。如果上面有错,请大佬多多指教!加油吧!!!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值