日期:2014-05-16  浏览次数:20479 次

ExtJs中继承的实现与理解—extend

以下总结参考网络上资源

?

Ext中实现类的继承

extend (Object subclass,Object superclass,[Object overrides] : Object)

?
第一个参数:子类
第二个参数:父类
第三个参数:要覆盖的属性。
这里需要强调一下,子类继承下来的是父类中通过superclass.prototype方式定义的属性(包括用此方法定义的函数),而不继承superclass中的定义的属性和方法,如果子类中的方法名与父类中相同则会覆盖。例子

??? 父类

BaseClass = function() {
 f1 = function() {
  alert("f1 in base");
 },
 f2 = function() {
  alert("f2 in base");
 }
}
BaseClass.prototype = {
 f3 : function() {
  alert("f3 in base");
 },
 f4 : function() {
  alert("f4 in base");
 }
};

?
??? 子类

ChildClass = function() {
}
// 继承
Ext.extend(ChildClass, BaseClass, {
   f1 : function() {
    alert("f1 in child");
   },
   f3 : function() {
    alert("f3 in child");
   }
  });

?
??? 实例化

var b = new ChildClass();
b.f1();// 调用子类中的实现
//b.f2();// 会报错,因为子类中没有该方法,并且父类中定义的f2是内部变量,作用域只有在内部可见(闭包)
b.f3();// 继承并覆盖,调用子类的中的实现
b.f4();// 继承,调用父类的中的实现

?

???? 补充:通过对 JavaScript 的原型继承的了解,可以知道,实例变量的优先级是高于 prototype 的,参见我之前写的文章javascript中静态方法、实例方法、内部方法和原型的一点见解 又如以下例子:
??? 父类

BaseClass = function() {
 this.f1 = function() {
  alert("f1 in base");
 },
 this.f2 = function() {
  alert("f2 in base");
 }
}

?
??? 子类

ChildClass = function() {
 ChildClass.superclass.constructor.call( this ); 
}
// 继承
Ext.extend(ChildClass, BaseClass, {
   f1 : function() {
    alert("f1 in child");
   },
   f3 : function() {
    alert("f3 in child");
   }
  });

?
??? 实例化

var b = new ChildClass();
b.f1();// 调用父类中的实现,注意不会调用子类中的实现
b.f2();// 调用父类中的实现
b.f3();// 调用子类中的实现

?

??? 分析:在 ChildClass.superclass.constructor.call(this); 这句上, BaseClass 的 f1 成了 ChildClass 的变量,而不是 ChildClass.prototype 。由于实例变量的优先级是高于 prototype 的,所以上面的这个代码是达不到 override 的功能的。


??? 了解了以上知识,下面讲解一下extend的实现,先看最简单的继承,实现原理,1、将子类的原型prototype设置为父类的一个实例,也就是说把父类的实例赋值给子类的prototype(这样子类就有了父类原型的所有成员),2、重新将子类原型的构造器设置为子类自己,也就是把子类赋值给子类原型的构造器。
??? 以下代码把 subFn 的 prototype 设置为 superFn 的一个实例,然后设置 subFn.prototype.constructor 为 subFn。

function Extend(subFn, superFn) {
 subFn.prototype = new superFn();
 subFn.prototype.constructor = subFn;
}

//父类
function Animal() {
 this.say1 = function() {
  alert("Animal");
 }
}
//子类
function Tiger() {
 this.say2 = function() {
  alert("Tiger");
 }

}
//继承应用
Extend(Tiger, Animal);
var tiger = new Tiger();
tiger.say1();// "Animal"
tiger.say2();// "Tiger"

?

???? 可以看到最简单的继承只做了两件事情,一是把 subFn 的 prototype 设置为 superFn 的一个实例,然后设置 subFn . prototype . constructor 为 subFn 。


Ext.extend 的代码


???? Ext.extend 函数中用到了 Ext.override ,这个函数把第二个参数中的所有对象复制到第一个对象的 prototype 中。首先贴上 Ext.override 函数的代码:

/**
         * Adds a list of functions to the prototype of an existing class, overwriting any existing methods with the same name.
         * Usage:<pre><code>
Ext.override(MyClass, {
    newMethod1: function(){
        // etc.
    },
    newMethod2: function(foo){
        // etc.
    }
});
</code></pre>
         * @param {Object} origclass The class to override
         * @param {Object} overrides The list of functions to add to origClass.  This should be specified as an object literal
         * containing one or more methods.
         * @method override
         */
        override : function(origclass, overrides){
            if(overrides){
                var p = origclass.prototype;
                Ext.apply(p, overrides);
                if(Ext.isIE && overrides.hasOwnProperty('toString')){
                    p.toString = overrides.toString;
                }
            }
        }

?

??? 以下是 Ext.extend的代码

/** 
  * 继承,并由传递的值决定是否覆