契约

魔兽争霸3中死亡骑士(Death Knight)出生时就会说一句:

  The pact is sealed.

  契约已签订。

 

看过N多童话故事和电影的小伙伴们肯定熟悉这种场景:

  大反派斗不过主角,处于劣势时,就会与诸如恶魔签订契约,以自己的青春换取强大的力量,即:

    青春 --> 恶魔     恶魔  --> 力量  

 

我们把这个再改变一下:

  恶魔 【得到】{青春}  ->  {力量}

  看起来有点眼熟,这不就是function/method干的事情吗?

  

  function 与恶魔签订契约(青春) {
    return 力量;
  }

    

拿一个PHP简单的函数来说吧,此函数是这样的:

function getFullName($givenName, $surname) {
    return $givenName.' '.$surname;
}

    对于调用方来说,如此调用:$fullName = getFullName($realGivenName, $realSurname);

  输入 $realGivenName 和 $realSurname 不知道是否返回结果,有结果也不知道是什么。

  这里 $givenName和 $surname 两个形参对比之下就是契约条件,而返回的值就是契约回馈。

      

每天在敲代码,原来就是在写各种各样的契约,然后各个契约被各种各样的大反派(调用方)签订(调用)。

 

再来看Java的一个方法

public static String getFullName(String givenName, String surname) {
    return givenName + " " + surname;
}

 

 给一个String类型 和 一个String参数,返回一个String 类型的结果;

 

   

去跟PHP对比一下,发现Java的Method契约条件的限制更加严格了,而契约回馈的描述也更加准确了。

 

即PHP函数在调用时,函数形参如果不限制类型的话,可以是任意类型($givenName 可以是一个int,也可以是array,甚至是一个resource类型,或者干脆是null),

基于动态语言的特点,甚至还可以传多于/少于(少于的话PHP会报Warning级别的错误)function规定的参数数目进去!

 

所以在上面这种实现在遇到特殊情况下,就会出现意想不到的结果,因此具体实现要对变量类型、值做各种判断;

而Java在实现内则不需要做类型判断,只需要处理空的情况即可;

 

对于return 的结果来说,PHP function实现可以返回 null、int,array,resource... 又是不限制类型和值!契约回馈又是模糊的描述……

 

所以,PHP function/method 契约是模糊的,契约回馈的描述也是模糊,而Java则更加强调契约发起方和契约执行方的明确的责任;

 

如此这般,PHP 一个function/method 实现(契约执行方)就头大了,调用方(契约发起方)传过来的参数(契约条件)很有可能存在

意想不到的情况,于是就需要在实现内加类型判断, 处理空或者其他情况。调用方也不知道实现是否真的能达成契约描述(function/method名称,注释等)

那样的美好的结果,调用方又得对实现返回进行判断。

 

而Java则只是对象参数需要处理null的情况,因为有一步编译的过程,类型则不需要费心。即在通过编译后,契约双方的基本条件和回馈描述被保证了。

PS:这么一说,编译器(Compiler)听起来就像是一个公证人似的。

 

总的来说,PHP因为不必在声明变量或者制定方法签名时声明类型,所以是弱契约。    

 

弱契约的好处是显而易见的:

  调用方的责任限制变少,执行方(实现)的责任 加重(即兼容 各种参数情况),那么只需要一个契约执行方,就可以满足多种调用方的情况。

  即一个function/method实现,调用方多种情况来调用都是没问题的;

  我们也可以把这种实现成为健壮的实现;

 

Java则是强契约,好处不必多说,但是劣势对比弱契约也是很明显,调用方参数若是出现了另外一种类型或者参数变多/变少,则不得不重载(Overload),

如果业务复杂起来,重载方法写起来简直是恶心;

 

 

说道这里泛型横空出世,我们可以理解泛型其实就是在强契约和弱契约之间的一种折中,即Method契约不再死板地限制某个具体类型,也不死板地规定

返回某个具体类型,而是规定为某一系列的类型,即在强契约的上弱化了一些,将类型限制放宽。

 

 

使用了泛型的方法,则可以满足调用方的某一系列的参数类型情况,让我们少些重载方法,减少了代码量 :)

 

 

return ;

 

posted @ 2017-05-09 01:30  Joynic  阅读(253)  评论(0编辑  收藏  举报