在JavaScript面向对象编程中使用继承(2)

    昨天扔了一堆JavaScript类'继承'的代码,这些代码其实并不是所有的都能正常的执行。不是我不原意写出都能好好执行的继承类代码,而是这些方法本身就各自有自己的优缺点。下面我分别说它们的原理和使用时注意事项。

    构造继承法的原理:

    构造继承法关键代码是function ArrayList01()中的:
  this.base = CollectionBase;
  
this.base(); 

    这里的base不是C#派生类中的base那个概念,完全就是一个任意的JavaScript变量名。调用this.base();其实就是执行的CollectionBase();,不过不是new CollectionBase();哦!没有new基类那么怎么得到CollectionBase中的方法和属性呢?这里使用了this作用域的一个hack,'欺骗'了脚本引擎。当我们从类ArrayList01的构造函数中调用this.base();时,在基类CollectionBase中的this就是ArrayList01的一个实例,于是执行CollectionBase的构造函数,就动态的把基类的成员和方法attach到ArrayList01实例中了。构造法的问题也就是从这里产生了,注意哦。

    构造继承法的缺陷:

    第一个问题,关键是出在上面那两段代码上,因为始终没有new基类呀。这样带来的问题就是不能把基类CollectionBase中的原型属性和方法attach到ArrayList01的实例中,啊,这样还算是什么继承啊?! 所以在上篇文章中我为了不改动CollectionBase类,而单独为其实现了一个Add()方法(只是为了统一示例代码而已)。解决这个缺陷的方法其实也很简单,就是要求基类不能使用prototype来导入属性和方法,而要把所有的属性和方法都写到构造函数中去,分别是:this.Attribute = ...; 和 this.Method = function() {...};这种形式。
    第二个问题,是this.base = CollectionBase;和this.base();必须写在派生类构造函数的最开头(不是一定要是第一行和第二行,而是它们的前面不能有this.xxx这种定义为ArrayList01导入的任何属性或方法),因为调用this.base();时会向this(ArrayList01的一个实例)中注入基类的属性和方法,如果基类中有和this中已导入的属性和方法重名的,就自动覆盖掉子类中的方法。
    第三个问题,是子类也不能使用prototype来导入属性和方法,这和问题二中的重名覆盖道理一样,由于prototype导入的属性和方法在子类一new的时候就生成了,所以也存在和基类重名而被覆盖的潜在错误威胁。解决办法,和基类编写规则一样不要使用prototype,并且将子类的属性和方法定义代码放在导入继承的代码(this.base = CollectionBase;this.base();)之后。

    构造继承法的示例:   
<script language="JavaScript">
document.write('构造继承法:
<br>');
var arrayList11 = new ArrayList01();
arrayList11.Add('a');
arrayList11.Add('b');
arrayList11.foo();
var arrayList12 = new ArrayList01();
arrayList12.Add('a');
arrayList12.Add('b');
arrayList12.Add('c');
arrayList12.foo();
</script>

    示例运行结果为:
构造继承法:
[class ArrayList01]: 
2: a,b
[class ArrayList01]: 
3: a,b,c

    小结一下:JavaScript的构造继承法其实看起来还是比较直观的,因为子类构造函数中有对基类构造函数的调用,似乎在语法上还比较容易被接受。可是由于没有new基类,带来了不能获得prototype导入的属性和方法的缺陷。解决这个缺陷的方法虽然不难,可是由此而给基类编写限制一个凌驾于JavaScript语法规范的规则,可操作性不是很好。子类也不能利用prototype特性来导入属性和方法,会与基类之间存在潜在的重名覆盖问题。所以对于复杂的基类,不推荐这种继承方法,因为类复杂了,使用prototype可以规范类代码,使类的定义看起来比较的舒服

    应用场景:小规模类之间的继承,基类和子类的属性方法在5-8个。还有就是以构造函数中赋值方式导入类的属性和方法,而不用prototype导入的类编写习惯的时候。

    to be continued ...   

posted on 2005-01-30 00:37  birdshome  阅读(3326)  评论(1编辑  收藏

导航