php的interface == 鸡肋?

话说当年,php5诞生的时候,向java,c++学了好多面向对象的语法元素。其中就有interface。在java圈子里,主流的观念是要面向接口编程而不是面向类编程,将接口与实现分离。记得在Spring in Action的例子里,要创建一个骑士对象,首先写一个Knight接口,里面定义了骑士可以做什么。具体怎么做则是在类KnightImpl里实现的。看上去似乎有一点麻烦。不过java大牛们教育我们,这是为了更好的灵活性。这样使用骑士的时候不用关心这是个什么样的骑士,而且可以在不修改代码,只修改工厂的配置文件,就可以用另一个实现来替换现有的实现。更寻常的说法是,比如Map接口,通常我们使用一个映射表的时候只要能够满足键值对应的操作就行。我们可以根据具体需要选用哈希表实现或是查找树实现,甚至自己定义一个存放在数据库中的Map。简单的说,接口定义了一组操作,实现了某个接口的对象也就能提供这个接口规定的一组操作。接口就像是一个协议或者说一个标准。这么说来,interface应该是一个好东西,似乎是面向接口编程所必不可少的,interface不就是接口的英文词么。那这篇文章的题目又是怎么回事呢?

还是拿例子说话。
interface Computer{
    function add($a, $b);
    function minus($a, $b);
….
}

class Mainframe implements Computer{
    function add($a, $b){
        //…
    }

    function minus($a, $b){
        //…
    }
}

class Calculator implements Computer{
    function add($a, $b){
        //…
    }

    function minus($a, $b){
        //…
    }
}

不管是大型机还是小计算器,都可以算加减法。想要算加法的时候只要拿一个实现了Computer接口的东西就行。比如
function doAdd(Computer $c, $a, $b){
    return $c->add($a, $b);
}
看起来不错。不过能算加减法的不仅仅是那些用电的东西。我国古代劳动人民的智慧结晶——算盘也能算加法。那么如果要拿算盘算加法,就要有一个算盘类。那这个算盘类该不该实现Computer接口呢?这个算盘似乎也算不上是一个计算机啊。或许该另外建立一个Calculatable的接口,让计算机和算盘都去实现这个接口,这样似乎就不错了。有时候我们只需要用到Calculatable的一部分功能。比如Calculatable定义了基本的加减乘除,但我们买菜算账的时候通常只需要加法。这时候如果用Calculatable的话就需要接受一些无用的东西。再用一个php的SPL里的例子。SPL里有一个ArrayAccess接口,可以让对象像数组一样用下标去访问。这是一个很有意思的语法糖。不过有时候只需要按下标读功能就可以了,但是为了要满足规定,还是要把ArrayAccess接口的所有方法都实现一遍,于是就要写好几个throw new Exception(‘xxx is not writable’);之类的东西。这实在有点罗嗦。

为什么不换一个写法呢?扔掉那些interface,直接写
class Mainframe{
    function add($a, $b){
        //…
    }

    function minus($a, $b){
        //…
    }
}

class Calculator{
    function add($a, $b){
        //…
    }

    function minus($a, $b){
        //…
    }
}

class Abacus{
    function add($a, $b){
        //…
    }

    function minus($a, $b){
        //…
    }
}
在需要计算的时候,也不用限定一定要是Computer,把对象直接扔过去。
function doAdd($c, $a, $b){
    return $c->add($a, $b);
}

如果在试图在一个不能算加法的东西比如易拉罐上执行add,解释器自然会报错。也就是说,只有满足接口的对象才能够正常运行。你看,不用interface一样可以实现面向接口编程,而且更加灵活。

不用interface搞面向接口编程这听起来还是有点玄乎。毕竟这个interface就是接口的英文单词啊。好吧,interface确实是英文单词,但并不代表interface这个语法元素就等价于接口。就好像把狗的尾巴也叫做腿,这狗也不是就有了五条腿。interface只是叫了这个名字而已。当然,interface在一定程度上也为面向接口编程提供了方便,比如提供了编译期的检查。而且对于强类型语言来说,这样的语法元素是很重要的,比如java。而对于弱类型语言,比如php,却不是必须的。而对于一些更动态的语言,比如python,ruby来说,更是很难相容的。

 

12 thoughts on “php的interface == 鸡肋?

  1. YERNSUN May 17, 2010 / 2:46 pm

    这么说来你也不必用面向对象了!
    博主用个简单的运算就说interface是鸡肋,看看你的参数,要我想算三个数的平方和楼主的参数岂不是要十几个。
    也不想想面向对向是用来干嘛的,一个小工项目也没必要大量使用面向对象…
    以为自己能干点什么就牛叉了,有和自己去写个引擎…

  2. 1 April 16, 2009 / 11:04 am

    比来比去有意义吗

  3. lonelyteers February 25, 2009 / 12:27 pm

    拜读了。谢,还记得我吗?

  4. 路过 April 21, 2008 / 11:32 pm

    晕啊。。。。
    怎么选择这么个主题,看得我眼花了

  5. wps2000 November 21, 2007 / 6:05 pm

    凡是超类型都算是接口吧~~~
    面向接口编程现在我把它理解成面向超类型编程了。应该说,在设计框架的时候interface才会发挥一点做作用吧,貌似像我这种打字员是无法体会的真正的精髓的。type hints 我倒认为是一个好东西,自己的函数,方法之类的,只要能使用,我一定使用。type hints在一定程度上可以减轻调试的负担

  6. giky October 10, 2007 / 10:39 pm

    接口还是很有用嘀,很多设计模式都是靠接口实现。至于说接口多余,那就是接口设计的不对了。需要二口的插座你偏要设计个三口的,那当然会有多余。

  7. 学弟 September 21, 2007 / 11:16 am

    业哥。。。真牛。。。
    学习中。。

  8. cid73 September 18, 2007 / 1:07 pm

    所以说还是 SOA 最能解决问题. 我们不要用框架, 利用 Web server 来传送, 一切协作都使用 XML, 通过公用(或事先协定)的 DTD/Schema 来校验. 硬件成本会增加, 但是开发成本会大大下降. 对程序员的要求也将大大下降, 我才不理你怎么写, 只要你传过来的 XML 可以通过校验就没问题, 呵呵.

  9. cid73 September 18, 2007 / 5:17 am

    Java 的函数可以重载, 接口就是协作中的契约. PHP 不支持函数重载, 但是接口还是可以限制传入参数的数量和类型的(虽然不那么地道), 在协作中还是有一定作用的. 不过我倒希望 PHP 快点加入强类型支持, 类型安全总是一个话题.

  10. 虎虎 September 16, 2007 / 12:59 pm

    我不懂编程序!

  11. 老王 September 15, 2007 / 4:08 pm

    我赞同这样的判断,php中的interface和type hinting是鸡肋

  12. D.c. September 15, 2007 / 2:15 pm

    脚本语言本来就没必要搞那么复杂的东西
    历史上似乎PHP每次想引入些新功能最后都被证明是好心办坏事
    PHP5开始已经不伦不类了,所以就放弃了…
    话说看Spring in Action不是看接口,而是看IoC和AOP阿..

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s