站在巨人的肩膀上编程----1:深入浅出谈多态

  本文结合示例程序分析面向编程语言的多态特性的几大作用,正因为有这几大作用,能够解决程序员在编程中遇到的一系列烦恼,所以多态才会被设计出来并被广泛应用。

  那么上述所说的程序员面对的烦恼都是哪些呢?又是如何通过多态来解决这一系列烦恼的呢?

  我个人认为,作为程序员,非常有必要知其然,且知其所以然,也就是说不仅需要熟练使用编程语言来完成编程目标,也要知道为什么要这样编程。我认为编程语言的使用者都是站在巨人的肩膀上来完成目标的,因为编程语言的发明者以及其改进者,早已对我们当前碰到的问题踩过坑或者预想过,所以在编程语言中加入了一系列特性,让后面的编程者通过该特性的运用,直接越过这一个坑,故曰:站在巨人的肩膀上编程。


多态作用一:父类引用可调用子类方法 —— 代码复用

  举例说明,我们要对物体 sayHello,这个物体可以是一个人,也可以是一只狗或者一颗树,那么我们要定义一个 sayHello 的方法去做这件事情的话,我们可以这样写:

class Person {
    public String tellName () {
        return "person";
    }
}

class Dog {
    public String tellName () {
        return "dog";
    }
}

public static void sayHello (Person person) {
    System.out.println("Hello " + person.tellName());
}

public static void sayHello (Dog dog) {
    System.out.println("Hello " + dog.tellName());
}

  当来的是一个人,我们跟他说: Hello person,当来的是一只狗,我们跟他说: Hello dog。会发现这样写代码的话会需要定义多个同名的方法,那么能不能复用代码去完成所有这些功能呢?那就要运用到抽象,我们不管来者何人,都把它认为是一个物体:Objects,我让“看门狗”(Java虚拟机)去帮我识别来的物体是什么,专业术语谓之动态绑定,也就是程序运行时根据对象的实际类型寻找实际该调用的代码。好,“看门狗”说有个人来了,那我说:Hello person,“看门狗”说有棵树飞过来了,那我说:Hello tree…… 我们把"来者“统一抽象成物体,那我们可以得到以下代码:

abstract class Objects {
    
    abstract public String tellName();
}

class Person extends Objects {
    
    public String tellName() {
        return "person";
    }
}

class Dog extends Objects {

    public String tellName() {
        return "dog";
    }
}

public static void sayHello (Objects obj) {
    System.out.println("Hello "+ obj.tellName());
}

  当然,前提是这个抽象的父类拥有一个子类共有的方法,例如这里是 tellName,实际上面向对象编程的三大特性(封装、继承、多态)中的另一个特性——继承就已经解决了这个问题,父类拥有的方法均会被子类继承,所以对于一个父类方法,使用父类引用(C++里面叫指针)一样可以去调用子类的方法,只要最终实例化的对象是子类的即可。


多态作用二:子类可基于父类进行拓展 —— 代码复用

  是的,又是代码复用,程序员的“懒惰”使他埋头钻研于各类新技巧解决他的烦恼。事实上,人类制造的很多工具,都是因为他的“懒惰”,或者说为了追求更高效,为了在有限的生命绽放更大的光辉。好像扯远了……

  因为多态这一特性,我们可以在继承父类既有的“能力”之外,还可以继续拓展我们的“能力”——方法。

  举个例子,很久很久以前,女娲神仙和了一盘泥巴,造了一种生物(姑且叫它“植物人”),它具有心脏、大脑以及一张嘴巴,她发现“植物人”能够帮她去用大脑处理一堆问题,并能够用嘴巴说出它思考过后给出的解决方案,太牛逼了是不是。

  后来,女娲想着,能不能有一种生物,替她去实践这些解决方案呢?于是她想到,另外造一个生物太耗费我时间了,我还得抓紧时间去做美容呢,况且,我的泥巴可珍贵着呢,可不能胡用。于是她在“植物人”的基础上,给它加上了四肢。这就不得了了,“植物人”拥有了四肢就进化成了人类,它具有行动能力,能够去办很多事情,这可让女娲神仙多省心呀…… 故事讲完了,来看示例代码:

class Body {  
    
    private Head head;
    private Mouth mouth;
    
    public void thinking () {
        System.out.println("Hey, I can think because I have head.");
    }
    
    public void talking () {
        System.out.println("Hey, I can talk because I have mouth.");
    }
}  
  
class Human extends Body {
    
    private Arms arms;
    private Legs legs;
    
    public void running () {
        System.out.println("Hey, I can run because I have arms and legs.");
    }
    
}

  于是,当女娲神仙发现了这种好方法,她又造了一个人类的模版(抽象基类),基于此模板,添加一些特色功能,分别进化出男人和女人(实体子类),有了这种高效的方法,女娲神仙就开始了高速且源源不断的造人活动,随着一大波人类来袭,复杂的人类社会就开始了……


  好了,本篇就说这两个作用吧,当然多态的作用不止于此。面向对象编程作为一种伟大的发明,其强大只有在进行大量的编程过程中,才能深有体会。在编程过程中,我们应该多去思考为什么要这样编程,我能不能按别的思路去写代码?然后也许就会顿悟:哦!原来用旧的思路写确实会增加很多代码量,使用特性能够复用很多代码。这就是所谓的站在巨人肩膀上编程,或者说:巨人们已经掉进过坑里面了,他们的身躯已经把坑给填平了…… 哈哈~ 编程就是这么有趣。


  参考文献: 《 Thinking in Java 》

标签: 多态, 代码复用

添加新评论