您的位置:首页 > Web前端 > JavaScript

Classes in JScript – Part III 类的继承与封装

2007-11-12 14:19 260 查看
原文地址Classes in JScript – Part III: Class Hierarchy and Data Encapsulation

原文发表日期】Published Wednesday, October 31, 2007 8:10 在这篇博客中,我们将会来讨论如何在Jscript中实现类的继承与封装。 我仍然会使用之前第一部分第二部分文章中所使用的示例代码,并按需要来修改它们。 function Rectangle (ht, wt) { this.height = ht; this.width=wt; } Rectangle.prototype.area = function() {return this.height * this.width;} var rect1 = new Rectangle(5,10); var rect2 = new Rectangle(2,4); var rect1Area = rect1.area(); // rect1.area() will return 50. var rect2Area = rect2.area(); // rect2.area() will return 8. 在支持而向对象的语言中都会有两个不同而有联系的概念:类和实例。在第一篇文章中,我们定义的类是对象的框架结构,在类中定义了对象所拥有的字段属性,类别和对对象进行操作的方法。类是一个抽象的概念,一个类可以拥有很多不同的实例,每个实例都有自己不同的状态。 但是,基于prototype 的语言(比如:JScript),并没有对类和实例进行区分。这种语言中只有对象(objects)的概念。基于prototype的语言中,都提供了一个prototype对象,这个对象可以为新对象提供初始化属性的模板。任何对象都可以给prototype属性赋不同的值。 在支持Class的语言中,类的继承关可以通过类的来定义。定义类的时候,我们可以指定它继承于一个已经存在的类。 前面的文章中已经介绍过了,在Jscript中并不支持Class关键字(来定义类)。它是通过Constructor和Prototype对象来模拟类。因此,类的继承也可以通过Constructor和Prototype来实现。 让我们扩展上类的例子,定义一个带有坐标的Rectangle。理论上,我们可能需要定义8个点(topLeftX, topLeftY, topRight(X & Y),bottomLeft(X & Y) and bottomRight(X & Y) )才能完全定位坐标,但是我们这里将它简化一下,只需要前面两个。 定义PositionedRectangle: function PositionedRectangle (topLeftX,topLeftY,height,width) { this.topLeftX = topLeftX; this.topLeftY = topLeftY; } 修改PositionedRectangle的prototype值为Rectangle的一个实例。 PositionedRectangle.prototype = new Rectangle; 类似的,我们可以创建一个PositionedRectangle对象。 var prObj = new PositionedRectangle(2,3,4,5);prObj创建的时候,它会从Rectangle类中继承height和width,因为我们修改了PositionedRectangle的值为Rectangle的一个实例。 通过下面的代码,我们可以看到topLeftX,topLeftY,height,width不同的值: alert(prObj.topLeftX+" "+ prObj.topLeftY+" "+ prObj.height+" "+ prObj.width); // 显示 2 3 undefined undefined 因为Rectangle的height 和 width,未被赋值,所以我们看到它们的值是undefined。这就是以上做法的不完善的地方。如果我们像下面这样在构造器中给height和width属性设置默认值: function Rectangle () { this.height = 1; this.width=1; } 这样的结果会是2 3 1 1。但是它不是我们希望的结果,因为参数值未被传递下来。 为了解决这个问题,我们可以往构造器中添加一些代码: function PositionedRectangle (topLeftX,topLeftY,height,width) { this.topLeftX = topLeftX; this.topLeftY = topLeftY; //其中一种做法分别新建这两个属性 this.height = height; this.width=width; //另一种做法是调用基类的构造器 Rectangle(height,width); (译注:2008/1/16更新 原代码的调用有误,应该是这样:Rectangle.call(this,height,width); ) } PositionedRectangle.prototype = new Rectangle; var prObj = new PositionedRectangle(2,3,4,5); alert(prObj.topLeftX+" "+ prObj.topLeftY+" "+ prObj.height+" "+ prObj.width); 这样的输出结果会是2 3 4 5。这里我们做调用子类的一个普通法一样调用基类构造器,来设置正确的值。 它是如何工作的? 1. 首先,new操作符会创建一个普通的对象,将它的prototype属性的值赋给PositionedRectangle.prototype.。 2. New操作符传入一个新创建的对象给PositionedRectangle构造器,用this关键字来表示它。 3. 接下来初始化topLeftX和topLeftX。 4. 在新创建的对象作用域里调用Rectangle方法,来初始化height和width的值。 5. 在PositionedRectangle构造器返回时,将新创建的对象赋值给prObj。 如果我们以后创建一个PositionedRectangle的子类,那么就需要为子类的prototype属性赋值为PositionedRectangle的实例,然后在子类的构造器里像调用普通方法一样调基类的构造器。 数据封装 所谓的数据封装,就是说对象的数据成员只能内部访问,而通过一些公用的方法来暴露给外界。简单的说,就是外界无法直接访问和修改对象的属性。 在Jscript中,默认情况下所有的成员都是公有的,不需要通过方法来访问和修改这些成员。像上面的例子: ect1.height = 10; //会将height的值修改为10 那么我们该如何来封装成员呢? 答案就是能过使用内嵌函数,而不要在对象成员前加this关键字。让我们来为Rectangle增加一个colour属性。我们要将colour定义为私有的,而通过公有函数来向对界开放。 function Rectangle (ht, wt) { this.height = ht; this.width=wt; var colour = null; // colour now is a private member of this class. this.setColour = setColour; this.getColour=getColour; //These methods will be used to access / modify colour. function setColour (passedColour) { colour =passedColour; } function getColour() { return colour; } } ar rect1 = new Rectangle(5,10); rect1.setColour (“blue”); // 设置颜色为blue. alert(rect1.getColour); // 这里会弹出blue alert(rect1.colour) // 这里会弹出undefined Rect1.colour =”red”; /*这里并不会弹出任何错误,也不会修改原先的color属性的值,而是会在Rect1对象上创建一个公有的colour属性。 */ alert(rect1.getColour); //这里仍然会弹出blue alert(rect1.colour) // 而这里则会弹出red. 这就是我们定义私有成员,和通过公有方法来访问私有成员的途径。这样我们就可以达到封装数据的目的了。 到这里所介绍的并不是在Jscript中实现类的全部,但是做为一个开始已经是足够了。希望这个博客对你是有用的,并且你也喜欢阅读。 这三篇就是我们计划在这个主题上的所有讨论了。这里还有一些有用的链接: http://www.webdevelopersjournal.com/articles/jsintro3/js_begin3.html http://dean.edwards.name/weblog/2006/03/base/ http://www.crockford.com/javascript/inheritance.html http://devedge-temp.mozilla.org/viewsource/2001/oop-javascript/ 谢谢, Ritesh SDET, JScript Team.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: