关闭

Simulating class in JavaScript -- 7

144人阅读 评论(0) 收藏 举报

9.6 Extending Without Inheriting

这章里之前创建子类的讨论解释了怎样创建一个新的类,继承另一个的方法。JavaScript是一个灵活的语言,子类化和继承不是仅有的方式其扩展一个类。因为JavaScript函数是数据值,你可以简单地从一个类里拷贝或者借一些函数用在另一个里。下面的例子一个函数借用了一个类里的所有的方法和拷贝另一个类的prototype对象。


//Borrow methods from one class for use by another.
//The arguments should be the constructor functions for the classes.
//Method of built-in types such as Object, Array, Date, and RegExp are
//not enumerable and cannot be borrowed with this method.
function borrowMethods(borrowFrom, addTo) {
    var from = borrowFrom.prototype;   //prototype object to borrow from
    var to = addTo.prototype;   //prototype object to extend

    for (m in from) { // Loop through all properties of the prototype
        if (typeof from[m] != "function") continue; // ignore nofunctions
        to[m] = from[m];
    }

}

很多定义好的方法都与类是紧密相连的,把他们拿出来用刀别的类里是毫无意义的。但是也有可能写一些平常的方法让它们可以适用于别的类或则别的类的确定的属性。下面的例子包括了两个类,定义了一些方法可以让别的类借用。像这种设计成为了借用的类叫mixin classes 或者  mixins.

//This class isn't good for much on its own. But it does define a 
//generic toString() method that may be of interest to other classes.
function GenericToString() {}
GenericToString.prototype.toString = function () {
    var props = [];
    for (var name in this) {
        if (!this.hasOwnProperty(name)) continue;
        var value = this[name];
        var s = name + ":";
        switch (typeof value) {
            case 'function':
                s += "function";
                break;
            case 'object':
                if (value instanceof Array) s += "array";
                else s += value.toString();
                break;
            default:
                s += String(value);
                break;
        }
        props.push(s);
    }
    return "{" + props.join(", ") + "}";
}

//This mixin class defines an equals() method that can compare
//simple objects for equality.
function GenericEquals() { }
GenericEquals.prototype.equals = function (that) {
    if (this == that) return true;

    //this and that are equal only if this has all the properties of 
    //that and doesn't have any addtional properties
    //Note that we don't do deep comparison. Property values 
    //must be === to each other. So properies that refer to objects 
    //must refer to the same object, not objects that are equals()
    var propsInThat = 0;
    for (var name in that) {
        propsInThat++;
        if (this[name] !== that[name]) return false;
    }

    //Now make sure that this object doesn't have addtional props
    var propsInThis = 0;
    for (name in this) propsInThis++;

    //If this has addtional properties, then they are not equal
    if (propsInThis != propsInThat) return false;
    //The two objects appear to be equal.
    return true;


这里是一个简单的Rectangle类,借用了定义在mixin类的toString()方法和equals()方法:

    function Rectangle(x, y, w, h) {
        this.x = x;
        this.y = y;
        this.width = w;
        this.height = h;
    }
    Rectangle.prototype.area = function () { return this.width * this.height; }

    //Borrow some more methods for it
    borrowMethods(GenericEquals, Rectangle);
    borrowMethods(GenericToString, Rectangle);


两个mixins类都没有constructor函数,但是也有可能去借用构造函数。接下来的代码,一个新的类被创建成名为ColoredRectangle。 它从Rectangle里继承了rectangle的功能和借用了构造函数和mixin的一个叫Colored的方法:


//This mixin has a method that depends on its contructor. Both the 
//constructor and the method must be borrowed.

function Colored(c) { this.color = c; }
Colored.prototype.getColor = function () { return this.color; }

//Define the constructor for a new class.
function ColoredRectangle(x, y, w, h, c) {
    this.superclass(x, y, w, h); //Invoke superclass constructor
    Colored.call(this, c); // and borrow the Colored constructor
}

//Set up the prototype object to inherit methods from Rectangle
ColoredRectangle.prototype = new Rectangle();
ColoredRectangle.prototype.constructor = ColoredRectangle;
ColoredRectangle.prototype.superclass = Rectangle;

//And borrow the methods  of Colored for our new class
borrowMethods(Colored, ColoredRectangle);

ColoredRectangle类扩展和继承了Rectangle和借用了Colored的方法。Rectangle它本身继承了Object和借用了GenericEquals()和GenericToString()。虽然严格的类比都有可能,但你可以想到这是作为一种对样化的继承。因为ColoredRectangle类借用了Colored的方法,ColoredRectangle类的实例也可以被认为是Colored的实例。instanceof这个操作不会告诉你这个,但是在后面,,我们将会写一个更加平凡的方法去检测一个类是继承还是借用了一个明确的类。



0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:4314次
    • 积分:159
    • 等级:
    • 排名:千里之外
    • 原创:13篇
    • 转载:0篇
    • 译文:0篇
    • 评论:0条