浅谈多态以及php的实现方法

来源:互联网 发布:java log4j 中文乱码 编辑:程序博客网 时间:2024/06/05 08:21

先简单说一下多态
多态的三大特征:

  • 子类继承父类
  • 子类重写父类
  • 父类指向子类

多态实现的前提:必须是类与类之间要有关系,要么继承,要么实现,存在重写(override),其实就是抽象函数或接口。
多态的应用:父类对象的引用指向子类对象,其实本质上就是一个向上转型。
举个模型例子,一家公司有员工类(Employee),还有其子类:销售(Sales)、市场(Market)、工程师(Engineer)等。某一天老板招待所有的员工开了个短会,完了之后对所有的员工(Employee)说,大家回去工作吧。在这里我们可以认为老板调用了所有员工对象的continueToWork()方法,而不是对一个个员工细说做什么工作,比如对销售部说你去制定销售计划(调用makeSalePlan();),对市场部说你去制定产品的价格(调用makeProductPrice();)….这种逐个细说的方式并不是面向对象,而是面向个体。可以确定的是,员工类应该有一个方法continueToWork()。而员工如何实现他们工作的方法却只有精确到子类才能确定,因为不同的员工的工作方式是不一样的。因此,我们很多时候只需要关心对象的父类型,而忽略更精确的子类型,比如上面老板叫大家回去工作时,他对全体员工说的,主要指的是全体员工类型。
上述的UML图:
这里写图片描述

多态的好处:大大提高程序的扩展,增强系统的灵活性,降低模块间的耦合。
具体Java代码实现如下:

abstract class Employee{    abstract void continueToWork();}class Sales extends Employee{    private void makeSalePlan(){        System.out.println("make sale plan");    }    public void continueToWork(){        makeSalePlan();    }}class Market extends Employee{    private void makeProductPrice(){        System.out.println("make product price");    }    public void continueToWork(){        makeProductPrice();    }}class Engineer extends Employee{    private void makeNewProduct(){        System.out.println("make new product");    }    public void continueToWork(){        makeNewProduct();    }}

错误的调用示范:

class Demo{    public static void main(String[] args){        Sales s = new Sales();        s.continueToWork();        Market m = new Market();        m.continueToWork();        Engineer e = new Engineer();        e.continueToWork();    }}

以上的这种调用并不能称为多态,虽然看起来都通过调用continueToWork()来得到结果,但是并不是通过同一接口来实现的,这只是不同类的对象都有相同名称的接口方法,用上述模型来说,就是老板单独对销售部说你去工作,单独对市场部说你去工作,单独对工程师说你去工作,而不是对所有的员工说。

正确的调用方式:

class Demo{    public static void main(String[] args){        Work(new Sales());//Employee e = new Sales();        Work(new Market());//Employee e = new Market();        Work(new Engineer());//Employee e = new Engineer();    }    public static void Work(Employee e){        e.continueToWork();    }}

上面通过调用统一的接口Work()来工作,这种调用才是多态。

还可以利用重载来实现伪多态:(注:本作者认为重载不属于多态的范畴,但是重载这种语言特性是可以帮助我们来实现伪多态的,具体请见本人的另一篇博文:《重载不应归在多态的范畴内》)

class Demo{    public static void main(String[] args){        Work(new Sales());        Work(new Market());        Work(new Engineer());    }    public static void Work(Sales s){        s.continueToWork();    }    public static void Work(Market m){        m.continueToWork();    }    public static void Work(Engineer e){        e.continueToWork();    }}

为什么我称上面调用是伪多态呢?因为上述的这种方式,细究其实跟第一种错误调用方式是一样的,只不过利用了重载加以封装,使得看起来是通过统一的接口Work()来工作,但其实它并没有让父类对象的引用指向子类对象。

最后附上php代码实现多态:

<?phpabstract class Employee{    abstract function continueToWork();}class Sales extends Employee{    private function makeSalePlan(){        echo "make sale plan";    }    public function continueToWork(){        $this->makeSalePlan();    }}class Market extends Employee{    private function makeProductPrice(){        echo "make product price";    }    public function continueToWork(){        $this->makeProductPrice();    }}class Engineer extends Employee{    private function makeNewProduct(){        echo "make new product";    }    public function continueToWork(){        $this->makeNewProduct();    }}class Demo{    public function Work($employeeObj){        $employeeObj->continueToWork();    }}//调用$obj = new Demo();$obj->Work(new Sales());$obj->Work(new Market());$obj->Work(new Engineer());?>

参考资料:
CSDN帖子:重载是不是多态?重载是不是面向对象?
Qi_Yuan的博文《java之多态的使用》

1 0