这是一个系列文章,主要是从哲学的角度来为软件设计提供一些理论源头。我学哲学已经很长时间,但技术只是近年的事情。
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%相似的,比如哥哥可能鼻子像父亲,而弟弟可能只是嘴巴像父亲,而不会哥哥和弟弟鼻子和嘴巴都像父亲。换言之,在“家族相似性”的理论下,没有必然的统一的特征遗传给所有后代成员。家族之间是一种网状节点进行交叉相似的。
//待完成