继承还是关联?

这是一个系列文章,主要是从哲学的角度来为软件设计提供一些理论源头。我学哲学已经很长时间,但技术只是近年的事情。

JS是真正面向对象的一门语言,我所谓面向对象是指:它纯粹就是对象的。它与PHP这些面向对象(Object Oriented)语言不同的是:

  • 只有对象Object
  • 但没有类Class

但不对,我们不是同样用到了“new”这个关键字吗?比如:

var Foo=function(para){
    this.init=para;
    this.speak=function(){
        alert(this.init);
    }
}

foo=new Foo('i speak');

foo.speak();

其实这是一个小戏法,这里的new只是一个函数执行的方式,换言之,Foo这个函数通过new进行了执行。执行结果是产生了一个对象,但注意,不是实例对象。为了更清楚说明问题,我们来看看PHP通过类来构造实例对象的过程:

class Foo{
    public $init;
    public function speak(){
        echo $this->init;
    }
    public function __construct($para){
        $this->init=$para;
    }   
}

$foo=new Foo('i speak');
$foo->speak();

我们看出什么不同了吗?首先PHP定义类时用到了Class关键字,构造函数function __construct()是类Foo中的一个公开方法,而不像JS中只有构造函数而没有类(注1)。

我们再思考一个问题:在PHP中,如果我们要为实例化后的对象增加属性和方法会怎么办?我们通常会直接这样处理:

//动态增加一个实例属性
$foo->end='i speak end';
echo $foo->end;

//动态修改实例属性

$foo->init='i change my speak';
$foo->speak();

 

//动态增加一个实例方法
$foo->say=function(){
   echo 'i say';
};

$func = $foo->say;
$func();

//或则

call_user_func($foo->say);

但我们如果再思考一个需求:我们已经实例化了很多对象,如何才能实现统一修订他们的属性和方法?

这对于PHP这类面向对象语言似乎就不是那么方便实现了。这源自于程序的设计思路。PHP这类语言的类和对象是由继承来维系的,每个实例化后的对象就是一个实体(entity)。实体与实体之间是独立的,唯有实体和父类才有直系血缘关系(继承)。

类继承

 

针对这种设计思想,我们不免会提出如下几个为什么:

  • 为什么兄弟实例之间不能直接关联?为什么必须要借助父类才能共享由继承所带来的共性?实例对象A-a-1和实例对象A-a-2要交流,似乎只能通过父类A-a搭桥
  • 为什么这个继承链似乎到了实例就停止了?实例对象A-a-1如何产生它自己的后代?这没有道理,如果我们把实例对象视作兄弟姐妹,那么就天然产生后代进行继承需求
  • 为什么兄弟实例通过的继承下来的特性是统一的,也是唯一的?虽然我们可以通过多态对实例属性和方法进行修改。但这只是从技术手段而非逻辑层面解决了这个问题。我们知道维特根斯坦谈过一个“家族相似性”的理论,维特认为一个家族成员之间是不可能100%相似的,比如哥哥可能鼻子像父亲,而弟弟可能只是嘴巴像父亲,而不会哥哥和弟弟鼻子和嘴巴都像父亲。换言之,在“家族相似性”的理论下,没有必然的统一的特征遗传给所有后代成员。家族之间是一种网状节点进行交叉相似的。

 

 

 

 

//待完成

发表评论

您的电子邮箱地址不会被公开。