JavaScript中的类继承

  • 时间:
  • 浏览:0

  JavaScript是另另一个无class的面向对象语言,它使用原型继承而非类继承。这会让哪些使用传统面向对象语言如C++和Java的应用线程池池员们感到困惑。正如让人们让人们让人们让人们让人们让人们 所想看 的,JavaScript的原型继承比类继承具有更强的表现力。

  但首先,要搞清楚让人们让人们让人们让人们让人们让人们 为哪些这样关注继承?主要另另一个原应 。首先是方便类型的转换。让人们让人们让人们让人们让人们让人们 希望语言系统并能对哪些例如类的引用进行自动转换。而对于另另一个要求对引用对象进行显示转换的类型系统来说这样获得很少的类型安全性。这对于强类型语言来说很重要,怎么让在像JavaScript从前的松散型语言中,永远不这样对对象引用进行强制转换。

  第5个原应 是代码的复用。代码中处于絮状拥有相同法律妙招的对象是十分常见的。类都这样通过一组定义来创建它们。另外处于什么都有例如的对象也很普遍,哪些对象中这样少数有关加进去去和修改的法律妙招处于区别。类的继承都这样很有效地补救哪些问题图片,但原型继承更有效。

  为了说明什儿 点,让人们让人们让人们让人们让人们让人们 将介绍什么都有有语法糖,它允许让人们让人们让人们让人们让人们让人们 以例如于传统的class的语言来编写代码。怎么让让人们让人们让人们让人们让人们让人们 将介绍什么都有有有用的模式,哪些模式不适用于传统的class语言。最后,让人们让人们让人们让人们让人们让人们 将对语法糖进行解释。

  首先,让人们让人们让人们让人们让人们让人们 加进去去了另另一个Parenizor类,涵盖set和get另另一个法律妙招,分别用来设置和获取value,以及另另一个toString法律妙招,用来对parens中的value进行包装。

function Parenizor(value) {
    this.setValue(value);
}

Parenizor.method('setValue', function (value) {
    this.value = value;
    return this;
});

Parenizor.method('getValue', function () {
    return this.value;
});

Parenizor.method('toString', function () {
    return '(' + this.getValue() + ')';
});

  语法看起来很重不太一样,怎么让应该很好懂。法律妙招method接受法律妙招的名称和另另一个function,并将什儿 function作为公共法律妙招加进去去到类中。

  怎么让让人们让人们让人们让人们让人们让人们 都这样从前写:

myParenizor = new Parenizor(0);
myString = myParenizor.toString();

  正如你所期望的,myString的值为"(0)".

  现在让人们让人们让人们让人们让人们让人们 创建从前类继承Parenizor,除了toString法律妙招中对于value为空或0的情况会输出"-0-"外其余都和Parenizor相同。

function ZParenizor(value) {
    this.setValue(value);
}

ZParenizor.inherits(Parenizor);

ZParenizor.method('toString', function () {
    if (this.getValue()) {
        return this.uber('toString');
    }
    return "-0-";
});

  这里的inherits法律妙招与Java中的extends法律妙招例如,uber法律妙招也与Java中的super法律妙招例如。它允许另另一个法律妙招调用父类中的法律妙招(什么都有我改了名称以避开保留字的限制)。

  怎么让让人们让人们让人们让人们让人们让人们 都这样从前写:

myZParenizor = new ZParenizor(0);
myString = myZParenizor.toString();

  什儿 次,myString的值为"-0-".

  JavaScript这样类,怎么让让人们让人们让人们让人们让人们让人们 都这样通过编程来实现它。

  通过操作另另一个函数的原型对象,让人们让人们让人们让人们让人们让人们 都这样实现多重继承,从而使让人们让人们让人们让人们让人们让人们 都这样用多个类的法律妙招来构建另另一个类。混合多重继承将会难以实现,并将会处于法律妙招名称的冲突。让人们让人们让人们让人们让人们让人们 都这样在JavaScript中实现混合多重继承,怎么让在本例中让人们让人们让人们让人们让人们让人们 将使用另另一个更严格的被称之为Swiss继承的形式。

  假设另另一个NumberValue类,涵盖另另一个法律妙招setValue,该法律妙招检查value是是不是为某个特定范围内的数字,必要的之后 会抛出异常。让人们让人们让人们让人们让人们让人们 只这样ZParenizorsetValuesetRange法律妙招,而不这样toString法律妙招。这样让人们让人们让人们让人们让人们让人们 都这样从前写:

ZParenizor.swiss(NumberValue, 'setValue', 'setRange');

  从前只会将让人们让人们让人们让人们让人们让人们 这样的法律妙招加进去去到类中。

  ZParenizor还有另外并是不是写法。除了从Parenizor类继承,让人们让人们让人们让人们让人们让人们 还都这样在构造函数中调用Parenizor的构造函数,并传递返回的结果。通过什儿 法律妙招,让人们让人们让人们让人们让人们让人们 给构造函数加进去去特权法律妙招,而不让再去为其加进去去公共法律妙招。

function ZParenizor2(value) {
    var that = new Parenizor(value);
    that.toString = function () {
        if (this.getValue()) {
            return this.uber('toString');
        }
        return "-0-"
    };
    return that;
}

  类的继承是is-a关系(公有继承),而寄生继承是was-a-but-now's-a关系(私有继承与公有继承)。构造函数在对象的构造中发挥了很大的作用。注意ubersuper法律妙招仍然可用于特权法律妙招。

  JavaScript的动态性允许让人们让人们让人们让人们让人们让人们 加进去去或替换现有类的法律妙招,method法律妙招都这样随时被调用,从前类的所有实例在现在和将来后会有什儿 法律妙招。让人们让人们让人们让人们让人们让人们 都这样在任何之后 对另另一个类进行扩展。继承具有追溯性,让人们让人们让人们让人们让人们让人们 把什儿 叫做类的扩充(Class Augmentation),以补救与Java的extends产生混淆。

  在静态面向对象语言中,将会你我应该 另另一个对象与从前对象略微不同,就这样定义另另一个新的类。在JavaScript中,我应该 将法律妙招加进去去到单个的对象中,而不这样在定义额外的类。什儿 非常强大,将会你只这样写很少的类,怎么让类都都这样很简单。回想一下,JavaScript对象就像哈希表,我应该 随时加进去去新的值,将会值是function,这样它就成了另另一个法律妙招。

  怎么让在上端的示例中,我根本不这样ZParenizor类。我应该 简单地修改我的实例。

myParenizor = new Parenizor(0);
myParenizor.toString = function () {
    if (this.getValue()) {
        return this.uber('toString');
    }
    return "-0-";
};
myString = myParenizor.toString();

  我将toString法律妙招加进去去到我的myParenizor实例中,而这样使用任何形式的继承。让人们让人们让人们让人们让人们让人们 都这样修改单个的实例,将会语言是无class的。

  为了使上端的示例能正常工作,我写了5个sugar法律妙招。首先是method法律妙招,它将另另一个实例法律妙招加进去去到类中。

Function.prototype.method = function (name, func) {
    this.prototype[name] = func;
    return this;
};

  它在Function.prototype加进去去进去了另另一个公共法律妙招,怎么让所有的函数都通过Class Augmentation(类的扩充)获得了该法律妙招。它接受另另一个名称和另另一个函数,并将它们加进去去到函数的原型对象中。

  它返回this. 当我编写另另一个不这样返回值的法律妙招时,我通常后会返回this,从前就具有了另另一个级联式的编程风格。

  接下来是inherits法律妙招,它用来表示另另一个类从从前类继承。应该在另另一个类都被定义之后 再调用什儿 法律妙招,怎么让在继承类的法律妙招之后 加进去去该法律妙招。

Function.method('inherits', function (parent) {
    this.prototype = new parent();
    var d = {}, 
        p = this.prototype;
    this.prototype.constructor = parent; 
    this.method('uber', function uber(name) {
        if (!(name in d)) {
            d[name] = 0;
        }        
        var f, r, t = d[name], v = parent.prototype;
        if (t) {
            while (t) {
                v = v.constructor.prototype;
                t -= 1;
            }
            f = v[name];
        } else {
            f = p[name];
            if (f == this[name]) {
                f = v[name];
            }
        }
        d[name] += 1;
        r = f.apply(this, Array.prototype.slice.apply(arguments, [1]));
        d[name] -= 1;
        return r;
    });
    return this;
});

  让人们让人们让人们让人们让人们让人们 继续对Function进行扩充。让人们让人们让人们让人们让人们让人们 创建了另另一个父类的实例,并将其作为新的原型。让人们让人们让人们让人们让人们让人们 还修改了构造函数的字段,并将uber法律妙招加进去去到原型中。

  Uber法律妙招在此人 的原型中查找指定的法律妙招。这是在寄生继承或对象扩充的情况下调用的函数。将会让人们让人们让人们让人们让人们让人们 进行类的继承,这样让人们让人们让人们让人们让人们让人们 就这样在父类的原型中找到什儿 函数。Return话语使用函数的apply法律妙招来调用function,显示地设置this并传递另另一个数组参数。参数(将会有话语)从arguments数组中获取。可惜arguments数组也另另一个真正的数组,什么都有让人们让人们让人们让人们让人们让人们 不得不再次使用apply来调用的slice法律妙招。

  最后,是swiss法律妙招。

Function.method('swiss', function (parent) {
    for (var i = 1; i < arguments.length; i += 1) {
        var name = arguments[i];
        this.prototype[name] = parent.prototype[name];
    }
    return this;
});

  Swiss法律妙招对arguments进行遍历。对每另另一个name,它都从父类的原型中克隆技术另另一个成员到新类的原型中。

  JavaScript都这样像class语言一样来使用,但它也具有相当独特的表现力。让人们让人们让人们让人们让人们让人们 研究了类的继承,Swiss继承,寄生继承,类的扩充以及对象的扩充。什儿 絮状代码的复用模式来自于并是不是被认为比Java更小,更简单的语言。

  类的对象非常严格,要将另另一个新成员加进去去到对象中,唯一的法律妙招什么都有我创建另另一个新类。而在JavaScript中,对象是松散的,都这样通过简单的赋值操作将另另一个新成员加进去去到对象中。

  将会JavaScript中的对象非常灵活,什么都有你这样对类的层次特性进行不同的考虑。深度图次的特性并不太适用,相反,浅层次的特性更高效,更具有表现力。

我从事编写JavaScript代码将会有14年了,怎么让我从来这样发现这样使用uber函数。Super在class模式中十分重要,怎么让在原型和函数式模式中这样这样的。现在看来我早期尝试在JavaScript中支持class模式是另另一个错误。

原文地址:Classical Inheritance in JavaScript

相关链接:http://www.cnblogs.com/sanshi/archive/2009/07/08/1519036.html