- 多态是What
从字面意义来说,多态就是一种事物,多种形态;在编程中的的体现就是对于所写的代码,在编译时并不能确定它到底引用的是那个对象,而在具体的运行过程中,它会根据所需要的去调用对应的方法;这样的话,我们就不需要去修改源代码,就可以让引用变量绑定到各种不同的类实现上,从而导致该引用调用的具体方法随之改变,这就是多态性。
多态前提:类之间要有继承关系
来举个例子吧,比如说你爱打游戏,你的爱机拥有很多游戏。有一天,你闭着眼睛随机打开一款游戏,只有你登陆后才知道是啥游戏,你打开的游戏可能是:王者农药,英雄联盟,吃鸡,炉石等。这里可以表述为:
Game a = 王者农药;
Game b = 英雄联盟;
Game c = 吃鸡;
Game d = 炉石;
那么王者农药、英雄联盟、吃鸡、炉石都属于游戏的子类。我们只是通过游戏这一个父类就能够引用不同的子类,这就是多态——我们只有在运行的时候才会知道引用变量所指向的具体实例对象。
- 向上转型
向上转型是一种经典的多态的具体体现。在上面的例子中,Game是父类,WZ(王者),LM(联盟),CJ(吃鸡),LS(炉石)是子类,所谓的向上转型就是指:
WZNY a = new WZ();//实例化王者农药的对象
Game a = new WZ();//父类引用子类对象
注意:父类仅可以调用父类中定义的所有属性和方法
看一段代码:
class Game{
public String name;
public void func1(){
System.out.println(" Game的func");
func2();
}
public void func2(){
System.out.println(" Game的func");
}
}
class WZ extends Game{
// 父类中不存在该方法,向上转型后,父类一定不会引用该方法
public void func(String name){
System.out.println("王者农药的func");
}
//此处重写了Game的func2方法
// 父类中存在该方法,向上转型后,父类一定会引用该方法
@Override
public void func2(){
System.out.println("王者农药的func");
}
}
public class TestDemo {
public static void main(String[] args) {
Game game = new WZ();
game.func1();
}
}
运行结果:
Game的func
王者农药的func
运行结果显示,game先运行父类的func1(),接着运行WZ里面的func2();
在这个程序中子类WZ重载了父类Game的方法func1(),重写func2(),重载后的func(String name)与 fun1()不是同一个方法,由于父类中没有该方法,向上转型后会丢失该方法,所以执行WZ的Game类型引用是不能引用func(String name)方法。而子类WZ重写了fun2() ,那么指向WZ的Game引用会调用WZ中func2()方法。
总结如下:
(1)发生多态的前提——父类和子类必须有继承关系;
(2)父类引用子类对象时,只能引用父类的属性和方法,不能引用子类特有的或者是父类及子类都不具有的方法和属性;
(3)多态分为编译时多态和运行时多态。静多态主要指的是重载过程中发生的多态;动多态是的是运行时绑定,也称多态性;
- 如何实现多态?
Java实现多态有三个必要条件:继承、重写、向上转型。
继承实现多态⬇
代码:
public class Game {
private String name;
public void SetName(String name){
this.name = name;
}
public String getName(){
return name;
}
public Game(){
}
public String play(){
return "玩儿的是"+getName();
}
public String toString() {
return null;
}
}
public class LM extends Game{
public LM(){
SetName("英雄联盟");
}
//重写play方法
@Override
public String play(){
return "玩儿的是"+getName();
}
//重写toString 方法
@Override
public String toString() {
return "Game:"+getName();
}
}
public class WZ extends Game {
public WZ() {
SetName("王者");
}
@Override
public String play() {
return "玩儿的是" + getName();
}
@Override
public String toString() {
return "Game:" + getName();
}
}
public class TestDemo {
public static void main(String[] args) {
//定义父类数组
Game[] games = new Game[2];
//定义两个子类
WZ wz = new WZ();
LM lm = new LM();
//引用子类对象
games[0] = wz;
games[1] = lm;
for (int i = 0; i <2 ; i++) {
System.out.println(games[i].toString()+"===>"+games[i].play());
}
}
}
运行结果:
Game:王者===>玩儿的是王者
Game:英雄联盟===>玩儿的是英雄联盟
在上面的代码中王者、英雄联盟继承游戏这个父类,并且重写了play()和toString()方法,程序运行结果是调用子类中方法,输出王者和英雄联盟的名称,这就是多态的表现。不同的对象可以执行相同的行为,但是他们都需要通过自己的实现方式来执行,这就要得益于向上转型了。