PHP和Go实现多态的对比

多态的定义:对于接口的多种不同实现方式。

例如,程序中定义一个数据存储的 set() 接口,我们分别用 MySQL 和 Redis 实现了 set() 的不同内部逻辑,这两种实现方式就实现了 多态 的概念。

PHP 和 Go 实现多态的方式不同,PHP 作为动态类型的语言实现起来更加“松散”,Go 作为静态类型的语言则更加严格,当然其中还有语言本身的特性。

PHP 的实现

在我使用 PHP 的编程中,接口 interface 的使用频率屈指可数。原因是 PHP 作为动态类型的语言,本身就不需要声明变量类型,而这也是 PHP 能够快速开发 web 应用的核心之一。

接下来我们用程序设计多态的实现,假定一个实现面积计算的接口

interface Area
{
    public function get();
}

然后是两个实现:矩形和三角形

// 矩形
class Rectangle implements Area {

    public function getArea($a, $b)
    {
        return $a * $b;
    }
}

// 三角形
class Triangle implements Area {

    public function getArea($a, $b)
    {
        return $a * $b / 2;
    }
}

然后在使用时,就可以使用 interface 作为参数约束了

function myArea(Area $area, $a, $b) 
{
    return $area->getArea($a, $b);
}

但是因为 PHP 是动态类型的语言,不需要对参数的类型约束,完全可以用以上方式写代码,然后 interface 的定义就略显累赘,当然在框架设计中还是可以看到 interface 的使用场景,interface 确实明确的定义了实现的行为。但是开发中我不太会用 interface, 就算需要时也是用继承来实现,在 PHP 中继承完美覆盖了 interface 的作用,既可以约束子类实现的相同行为,还可以定义默认行为和扩展。

function myArea($area, $a, $b) 
{
    return $area->getArea($a, $b);
}

Go 的实现

Go 作为静态类型的语言,需要强制对变量的类型声明,这里再用 Go 实现一次上述简单的功能,首先定义接口:

type area interface {
	Get(int, int) int
}

然后定义矩形和三角形的实现:

// 矩形
type Rectangle struct {}

func (Rectangle) Get(a int, b int) int {
	return a * b
}


// 三角形
type Triangle struct {}

func (Triangle) Get(a int, b int) int {
	return a * b / 2
}

// 多态的调用
func myArea(ar area, a int, b int) int {
	return ar.Get(a, b)
}

总结

Go 的 interface 在项目中随处可见,而 PHP 开发中很少见。以上程序还存在一个问题,变量 a,b 义在两个实现中含义是不同的,这时扩展梯形时两个变量就会出现问题,需要将 a, b 放到 struct 结构体中,而 PHP 则是放在构造函数中。