JavaScript继承机制模拟实现
2004-09-07 13:22
686 查看
.Afr_ARTICLE_TITLE { font: NORMAL BOLD 14px "Tahoma"; } .Afr_CONTENTS { font: NORMAL NORMAL 12px "Tahoma"; line-height: 22px; } .Afr_CODE { font: NORMAL NORMAL 11px "Courier New"; line-height: 20px; width: 100%; background-color: #EEEEEE; padding: 5 10 5 10; } .Afr_COMMON { color: #55BB55; } .Afr_STRING { color: #EE0000; } 最近因为学校做网站设计,所以一直在ASP上和数据库上大费苦心。我在前一个阶段是做Java程序设计的。突然接到任务并学习ASP,所以我一直都热忠并善于利用JavaScript来构架ASP程序。 JavaScript的一个明显的优点就在于它可以定义和持有自己的对象。这一点好象是VBScript所无法比拟的。有了这一点,可以利用JavaScript进行更接近于面向对象的程序设计。也许这将使网站开发更有乐趣... 但有个严重的缺点!JavaScript不支持继承机制。不象Java那样,支持extends关键字(虽然这个关键字在JavaScript中是保留字)。在微软的ASP.NET中,JavaScript才开始提供比较完善的对继承机制的支持。 PHP语言当然也有继承机制的支持,这些都叫我垂青... 不过现在我根本无法说服学校的老头子们买更好的域名空间,但是我也不想忍受ASP中无继承机制之苦,所以急中生智,也就有了一些成果! JavaScript根本不支持继承机制!这是可以肯定的。但是我们可以想办法做些手脚,模拟一个出来。 废话说了一堆,先来看一个例子: function Person() { public: // 注意这个public! this.GetName=Person_mfGetName; private: // 注意这个private! this.m_strName="Guest"; } function Person_mfGetName() { return this.m_strName; } var MyPerson=new Person(); MyPerson.GetName(); 注意上面的程序中的两个关键字:private 和 public。其实没有这样的用法,这只是我的习惯。 幸好在实际应用中不会有错。 你可以用任何输出语句来查看结果。当然结果一目了然,会在浏览器窗口中出现:Guest 字样。这是第一步!下面是关键一步:继承! function Student() // Extends Class: Person { EXTENDS: // 注意这个EXTENDS不能使用小写字母形式 this.Super=Person; // 定义指向其"父类构造器"。Super也不能用小写形式 this.Super(); // 调用其"父类构造器" private: this.m_nStudentID=0; } 使用EXTENDS这也是我的习惯,但要切记一定不能使用小写字母。因为extends是JavaScript中的保留字。 而随后定义和调用“父类构造器”就可以从“父类”那里“继承”所有的属性和方法。虽然在Student中并没有看到GetName()方法,但是却可以调用。因为他已经继承了Person的GetName()方法。 var MyStudent=new Student(); MyStudent.GetName(); // 调用"父类"的GetName(),结果为返回 "Guest" 关于JavaScript继承实现就是这样。只要牢记两步: 在“子类”中先定义一个指向“父类构造器”的函数(什么名字都可以,我习惯使用Super) 随后调用这个函数 这样就可以继承“父类”的所有属性和方法! 这种“继承机制”的原理是十分简单的。它的原理有点类似于C/C++语言中的include关键字的用法。当一个C/C++源程序在被编译的时候,编译器会将include字段直接替换成其所指文件的全部内容。而我所采用的JavaScript继承原理也是如此。先将一个“类”的成员函数指向“父类构造器”,在随后的函数调用中,自然就会把“父类”中的所有成员“添加”到该“类”中。 我现在有些怀疑的是,既然extends和super都是保留字,那为什么JavaScript却不支持继承呢?不知道有没有其他更好的办法?希望各位指点... 继续关于JavaScript继承机制的讨论。 不过,在继续讨论之前我们先来看一个实例: function Shape() { public: this.CalcuArea=Shape_mfCalcuArea; // 计算面积 } function Shape_mfCalcuArea() { // ... } 很明显的,这个Shape类下的CalcuArea()方法应该是个抽象函数。在Java中可以使用abstract关键字定义抽象函数,而在JavaScript中也没能支持这个特性。抽象函数不应该具有函数体,或者换句话说:在调用Shape.CalcuArea()时应该报错,并终止ASP脚本程序。从PHP程序设计中吸取一些设计经验,我们可以这样处理: function Shape_mfCalcuArea() { Response.Write("Error, Method Shape_mfCalcuArea Is Abstract"); Response.End(); } 这样做,就可以“迫使”自己在Shape的继承类中编写代码重载CalcuArea()方法。 你也可以直接让Shape类下的CalcuArea函数等于null,让服务器指出运行中的错误。 在Shape的继承类Rect中,我们可以通过改变CalcuArea变量所指向的函数,来模拟实现CalcuArea方法的重载。 function Rect() { EXTENDS: this.Super=Shape; this.Super(); OVERRIDE: this.CalcuArea=Rect_mfCalcuArea; } function Rect_mfCalcuArea() { // ... } 如果一个类中含有抽象函数,那么这个类必定是抽象类!抽象类是不能被实例化的,必须被子类继承。遗憾的是JavaScript也不支持抽象类定义(如果JavaScript真的支持“抽象类”机制,那么必定支持“继承”机制)。 如何实现抽象类机制,我想其大概思路应该和上面的抽象方法类似。还是利用 Response.End() 强制结束程序,并在这之前告之程序员:“该类是一个抽象类”。但不同的是这个方法要用在类的“构造器”中。这样就可以使一个抽象类不能被实例化。 JavaScript比较特殊,把类定义和构造器捆到一起。那么这样的形式是不是对的呢? function Shape() { Response.Write("Error, Class Shape Is Abstract"); Response.End(); // 其它代码 ... } var MyShape=new Shape(); // 会被告之出错 OK function Rect() { EXTENDS: this.Super=Shape; this.Super(); } var MyRect=new Rect(); // 仍会被告之出错 OH, NO 因为Shape是一个抽象类,所以在声明第一个MyShape对象时出现了警告。这是我们所期望的。而Rect类很好的继承了Shape类,但还是被告之“Error, Class Shape Is Abstract”。 这是我的关于JavaScript继承实现思想所留下的遗憾。必须再“变通”一下才能“完美”的实现抽象类。我还是采用了一种比较愚笨的精明方法。 说其“愚笨”,是因为这种方法通过判断变量值实现的。而又说其“精明”,是因为这个方法采用了最少的变量。 function Shape() { if(!this.Super) { Response.Write("Error, Class Shape Is Abstract"); Response.End(); } // 其它代码 ... } var MyShape=new Shape(); // 会被告之出错 OK function Rect() { EXTENDS: this.Super=Shape; this.Super(); } var MyRect=new Rect(); // 顺利继承 YES, OK 在调用Shape构造器时,Shape类中根本就没定义this.Super成员变量,所以肯定要警告错误信息。而在Rect类中,首先就定义了this.Super的去向:就是指向Shape的构造器。所以在随后的函数调用中,Shape类构造器不会认为this.Super为空了,也就放行让我们通过了... 这个抽象类的实现思想还可以继续获得延伸。比如一个抽象类的子类还是抽象类,那么你可以在这个子类构造器的最开始部分加入上面的判断代码。 通过这些示例,我想你可以从中扩充更广的面向对象的特性。篇幅有限,至此收笔。 如果你有好的提议,请与我联系:Afritxia2003@yahoo.com.cn 或 afritxia@hotmail.com 在文章结束的时候,我给出了一个运行于客户端的JavaScript脚本程序,可以通过查看页面源码来浏览。 这段代码演示了我上面所说的内容,绝不含有任何恶意程序。 // // 演示程序 function MSG() // MSG 抽象类定义 { ABSTRACT_CLASS: if(!this.Super) { document.write("Class MSG Is Abstract "); // Response.Write(...); // Response.End(); } public: this.Show=MSG_mfShow; // this.Show=null; private: this.m_nMainID=0; } function MSG_mfShow() { } function MSGCard() // MSGCard 抽象类定义, 继承自 MSG { ABSTRACT_CLASS: if(!this.Super) { document.write("Class MSGCard Is Abstract "); // Response.Write(...); // Response.End(); } EXTENDS: this.Super=MSG; this.Super(); } function BBSMainCard() { EXTENDS: this.Super=MSGCard; this.Super(); OVERRIDE: this.Show=BBSMC_Show; } function BBSMC_Show() { document.write("BBSMainCard.Show()"); document.write("BBSMainCard.m_nMainID="+this.m_nMainID); } var MyMSG=new MSG(); var MyMSGCard=new MSGCard(); var MyMainCard=new BBSMainCard(); MyMainCard.Show(); |
相关文章推荐
- 使用NSProxy实现消息转发机制,模拟多重继承
- Javascript 继承机制的实现
- Javascript继承机制的实现
- JavaScript实现继承机制(3)——通过原型链(prototype chaining)方式
- javascript 模拟java 实现继承的5种方式
- JavaScript继承机制的实现(未完)
- JavaScript高级程序设计 阅读笔记(十四) js继承机制的实现
- 基于JavaScript实现继承机制之原型链(prototype chaining)的详解
- Javascript 继承机制和构造方法链实现
- JavaScript实现继承机制(4)——构造函数+原型链混合方式
- 基于JavaScript实现继承机制之构造函数+原型链混合方式的使用详解
- JavaScript不使用prototype和new实现继承机制
- JavaScript简洁继承机制实现(不使用prototype和new)
- 基于JavaScript实现继承机制之调用call()与apply()的方法详解
- [iOS]使用NSProxy实现消息转发机制,模拟多重继承
- JavaScript 继承机制的实现(待续)
- javascript实现的下彩色泡泡及下雪(使用了某位大侠分享的继承机制)
- JavaScript继承机制的伪实现
- javascript继承机制的实现
- 阿里巴巴技术文章分享 Javascript继承机制的实现