浅谈Java的多态

浅谈Java的多态

一、什么是多态

Java初学者经常会困惑,这个多态(Polymorphism)有什么用。我当时学Java的时候也不明白。书上说,多态就是:父类引用指向子类对象:

class Father{}

class Son extends Father{}

public class Test {

    public static void main(String[] args) {
        Father f1 = new Father();
        Son s2 = new Son();
        Father f2 = new Son(); // 多态!!!
        
        System.out.println(f1 instanceof Father); // true
        System.out.println(f1 instanceof Son); // false
        
        System.out.println(f2 instanceof Father); // true
        System.out.println(f2 instanceof Son); // true
        System.out.println(s2 instanceof Father); // true
        System.out.println(s2 instanceof Son); // true
    }
}

通过例子,我们知道了,多态的f2不仅是Father的实例,而且也是Son的实例。可是这个多态又有什么用呢?

二、没有多态的日子

先忘记多态,看看没有多态的日子是什么样子的。我们来看个故事,然后再来用java代码来写一下这个故事:

老王出去玩,中午肚子饿了,于是他自然就要买东西吃(Eat)。他先买了个面包(Bread),然后又买了茶叶蛋(TeaEgg??)。到了晚上,他又饿了,这个时候他发现这里只有卖牛肉面的(Noodle),于是只好吃面啦。

于是我们用Java程序员的黑话就可以这样写:

2.1 定义各种食物的类:

public class Noodle{
    public String getName() {
        return "面条";
    }
}

public class Noodle{
    public String getName() {
        return "面条";
    }
}

public class TeaEgg{
    public String getName() {
        return "茶叶蛋";
    }
}

如果未来有更多的食物的话,我们就要添加新食物的类,如Apple类,Pizza类等。

2.2 老王是一个人(Person),人有吃(eat)的方法,定义人的方法

public class PersonOld {
    private String name;
    
    public PersonOld(String name) {
        this.name = name;
    }
    
    public void eat(Bread bread) {
        System.out.println(name + "正在吃" + bread.getName());
    }
    
    public void eat(Noodle noodle) {
        System.out.println(name + "正在吃" + noodle.getName());
    }
    
    public void eat(TeaEgg teaEgg) {
        System.out.println(name + "正在吃" + teaEgg.getName());
    }
}

好像很长哦,很坑爹哦。如果老王继续吃披萨,吃烤鸭,吃苹果……我们是不是要定义Person的吃Pizza方法,吃Apple方法:

public void eat(Pizza pizza){
    ...
}

public void eat(Apple apple){
    ...
}

2.3 测试的时候

public class FoodNonPolyTest {
    public static void main(String[] args) {
        PersonOld p1 = new PersonOld("老王");
        p1.eat(new Bread());
        p1.eat(new Noodle());
        p1.eat(new TeaEgg());
    }
}

运行的结果很老王:

老王正在吃面包
老王正在吃面条
老王正在吃茶叶蛋

成功了!可是世界上能吃的东西有多少种?上面的例子中,每增加一种食物,就要在PersonOld类里添加一个eat这个食物的方法,这样的话PersonOld这个类就要不断的被修改,而且改得毫无价值。

我们必须换个方法了。

三、通过例子看多态的应用

这些食物有什么特点?对,都是能吃的。我们可以定义一个接口,叫做Food,然后让所有的食物来实现这接口。

package core.polymorphism.food;

public interface Food {
    public String getName();
}
了解多态最好有接口(interface)的知识,具体最好看教材,我水平差,只能用打比方来说。

接口是什么呢?

接口的作用在Java里就类似于政府发的红头文件(interface,中文叫:接口),起一个规范的作用。例如:加班要给加班费,法定假日3倍工资……给少了就违法,给多了不要紧。但是政府的红头文件并不规定张三要给多少钱加班工资,李四要给多少。

而企业发加班费的时候,就会按照这个红头文件(interface)来执行(implements),来确定张三,李四的加班工资。

现在我们来实现这个接口:

public class Noodle implements Food{
    @Override
    public String getName() {
        return "面条";
    }
}

public class TeaEgg implements Food{
    @Override
    public String getName() {
        return "茶叶蛋";
    }
}

public class Bread implements Food{
    @Override
    public String getName() {
        return "面包";
    }
}

我们把Person这个类也改造一下,注意,我们在eat(Food food)方法这里作了重大的改动:

public class Person {
    private String name;
    
    public Person(String name) {
        this.name = name;
    }
    
    public void eat(Food food) {
        System.out.println(name + "正在吃" + food.getName());
    }
}

这里吃的并不是具体的面包,面条,茶叶蛋什么的,而是一个抽象的接口Food。这时,我们如果增加Apple类和Pizza类,只要这些新的类是Food接口的实现类,我们就完全没有必要改动这个Person类。这样的话我们维护程序方便多了。

测试一下:

public class FoodPolyTest {
    
    public static void main(String[] args) {
        Person p1 = new Person("老王");
        p1.eat(new Bread());
        p1.eat(new Noodle());
        p1.eat(new TeaEgg());
    }

}

结果必定也很老王:

老王正在吃面包
老王正在吃面条
老王正在吃茶叶蛋

好了,现在知道多态的好处了?

多态广泛应用于Java开发中,一定要掌握哦。

本人水平有限,请各位大牛指导。

编辑于 2017-09-06