多态
Java面向对象三大特性之多态
生活中: 同一种事物,由于条件不同,产生的结果也不同
编程中多态:同一个引用类型,使用不同的实例而执行不同操作
多态的前提:
1.继承或实现(后面讲接口)关系
2.父类的引用,或接口的应用(后面讲接口)指向子类对象
3.方法的重写
允许不同类的对象对同一消息做出响应。即同一消息可以根据发送对象的不同而采用多种不同的行为(发送消息就是函数调用)
在使用成员方法时:
父类引用指向子类
1.如果父类有此方法,子类没有,调用父类的
2.如果父类有,子类重写,调用子类的
3.如果父类没有,子类有,报错,需要强转
例:
`
package jicheng;
public class Animal {
public String type;
public String voice;
public void shout(){
System.out.println("动物太多,我不知道该怎么叫");
};
public void say(){
System.out.println("我是动物");
};
}
package jicheng;
public class Wolf extends Animal {
@Override
public void shout() {
System.out.println("哇呜");
}
public static void main(String[] args) {
Wolf w=new Wolf();
w.shout();
}
public void sing(){
System.out.println("狼爱上羊啊,爱的疯狂");
}
}
package Test;
import jicheng.Animal;
import jicheng.Wolf;
public class testDuotai {
public static void main(String[] args) {
//1.如果父类有,子类没有 调用继承父类
Animal an1=new Wolf();
an1.say();
//2.如果父类有,子类重写,调用子类的
Animal an2=new Wolf();
an2.shout();
//3.如果父类没有,子类有 报错,需要强转
/**
* Animal an3=new Wolf();
* an3.sing();
*/
Animal an3=new Wolf();
//添加强转,避免报错 方法1.
if(an3 instanceof Wolf){
Wolf w=(Wolf)an3;
w.sing();
}
//方法2.
if(Wolf.class==an3.getClass()){
Wolf w=(Wolf)an3;
w.sing();
}
}
}`
上面这个例子,是我在上一节例子上修改了几个类得到的,简单实现了父类引用指向子类,调用成员方法的3种情况
需要注意的是:强转的风险,一般情况下,强转可能出现问题,我们需要提前类型判断是否可以强转。
这里可以用两种方法:
1.判断类名。class和对象。getclass是否相等
2.InstanceOf
成员变量
1.父类有,子类没有 调用父类的
2.父类有,子类有 调用父类的
3.父类没有,子类有 报错
关于成员变量,读者可以自行测试,类似上面的代码简单实现。
以上就是多态,可能在这有人不明白,为什么要使用多态?多态有什么好处?
为什么要用多态呢?
原因:我们知道,封装可以隐藏实现细节,使得代码模块化;继承可以扩展已存在的代码模块(类);它们的目的都是为了——代码重用。而多态除了代码的复用性外,还可以解决项目中紧偶合的问题,提高程序的可扩展性.。耦合度讲的是模块模块之间,代码代码之间的关联度,通过对系统的分析把他分解成一个一个子模块,子模块提供稳定的接口,达到降低系统耦合度的的目的,模块模块之间尽量使用模块接口访问,而不是随意引用其他模块的成员变量。
多态有什么好处?
有两个好处:
1. 应用程序不必为每一个派生类编写功能调用,只需要对抽象基类进行处理即可。大大提高程序的可复用性。//继承
2. 派生类的功能可以被基类的方法或引用变量所调用,这叫向后兼容,可以提高可扩充性和可维护性。 //多态的真正作用,
多态在什么地方用?
可以用在方法的参数中和方法的返回类型中。
这节就这些吧,至此面向对象三大特性已经结束,如果仍然感到很困惑,不明白为什么要出现这东西。。。等等问题,可以网上再找资料,或者不妨暂时放下,只要现在能代码实现,等下节抽象类和接口讲完再回过头来看看这些,或许会有更深层次的体会。
最后吐槽一下markdown语法,不知道为啥,代码标签有时候生效,大部分情况无效,很头痛。。。