可转型参数类型的约定

从有类型声明的语言,比如C++/Java转到无类型声明语言时,最难理解的地方是参数类型。

比如javascript中,isNaN这个函数,有以下其怪的行为:

isNaN("abc")  // true

按类型语言的思维,这里应该先判断参数是否number类型,再做判断是否NaN的值。

事实上,isNaN先对参数做了包装,调用Number把参数包装成Number类型,再进行判断。

类型声明表达了一个强约定,参数必须满足约定才能完成功能,大多数强类型语言中需要通过多态达成通用型扩展。无类型声明语言这种对参数包装成期望类型的操作方式,以另一种方式达成了通用扩展。

isNaN({ valueOf: function() { return 0 }}) //false
isNaN({ valueOf: function() { return Number.NaN }}) //true

Javascript的通用性通过抽象操作来实现,所有对象通过调用通过valueOf()方法转型为基本对象,而Number和子类型对象返回自己的引用,实现操作一致性,且效率无损。

这就是在接口,鸭子类型之外的另一个参数类型约定。它可以简化为,实参只要可转化成形参类型。

在C++中可以通过实参定义一个类型转换函数,例如上面在C++中可能表达为:

class Number {
public:
  Number(int value);
  static const Number NaN;
  bool operator == (Number const& other);
};
class SomeObject {
  operator Number() const {
    return Number(0); //或者Number::NaN;
  }
};
bool isNaN(Number value) {
  return value == Number::NaN;
}

你可能感兴趣的:(可转型参数类型的约定)