实现类的步骤javascript
new Class
新建类,初始化的固定函数是initialize
,不能使用其它名称new Class
新建,父类在子类中,使用Extends:parentClass
来继承,Extends
与子类的方法名,同一级别this.parent(args)
implement
方法// 使用 Class.create 建立类 var Person = new Class({ // 初始函数固定为 initialize, initialize:function(name) { this.name = name; this.friends = ['jack', 'mark']; }, getName: function(){ console.log("My name is " + this.name); }, setFriends:function(friend){ this.friends.push(friend); }, getFriends:function(){ console.log(this.friends) } }); // 使用 implement 给类添加方法,子类能够继承该方法 Person.implement({ getAge:function(age){ console.log("My age is " + age); } }) // 子类经过 new Class 建立类 var Chinese = new Class({ // 子类经过 Extends 来继承父类 Extends:Person, initialize:function(name, addr){ this.parent(name); this.addr = addr; }, getAddr:function(){ console.log("My address is " + this.addr); } }); var Japanese = new Class({ Extends:Person, initialize:function(name){ this.parent(name); } }) // 实例化类 var men = new Chinese('allen', 'BeiJing'); men.getName(); // My name is allen men.getAge(23); // My age is 23 men.getAddr(); // My address is BeiJing // 如下验证 - 子类继承父类的属性,修改了以后,其余子类再次继承父类,父类的属性的值为什么不会改变 var allen = new Person(); allen.getFriends(); // ["jack", "mark"] var women = new Japanese(); women.setFriends("lisa"); women.getFriends(); // ["jack", "mark", "lisa"] var men = new Chinese(); men.setFriends('peter'); men.getFriends(); //["jack", "mark", "peter"] var wallen = new Person(); wallen.getFriends(); //["jack", "mark"]
JS
是如何实现类的方法,有几个重要的问题须要搞清楚java
this.parent(args)
在函数中使用,是如何作到在子类中的同名函数共存的implement
往类中添加方法的下面来经过Mootools.js
的class
来具体分析segmentfault
(function(){ // 新建一个 Class 的类,new Type 也是一个函数 var Class = this.Class = new Type('Class', function(params){ // 若是传入的 参数是方法,就把该函数看成初始化的方法 if (instanceOf(params, Function)) params = {initialize: params}; var newClass = function(){ // 解除属性里对其余对象的引用 reset(this); // 若是当前类正在构建,就返回当前类,不作任何操做 if (newClass.$prototyping) return this; // $caller 和 $family 是什么啊 this.$caller = null; this.$family = null; // 有初始化函数的话,就传入参数到该初始化函数,没有就返回自身 var value = (this.initialize) ? this.initialize.apply(this, arguments) : this; // 这句又是什么意思,一个 $caller ,一个 caller this.$caller = this.caller = null; return value; // extend(this) 把类的方法,都添加到当前新建的类中 // implement(params) 把 params 的全部方法都添加到当前类中 }.extend(this).implement(params); //指定 constructor ,以便使用 instanceOf 来验证 newClass.$constructor = Class; newClass.prototype.$constructor = newClass; // 指定当前类的父类是哪个 newClass.prototype.parent = parent; return newClass; }); /* 在子类拥有和父类同名方法时,使用 this.parent(args) 方法来调用父类的该方法 */ var parent = function(){ // :: 若是当前方法没有被调用,那么就说,parent 方法没有被调用 if (!this.$caller) throw new Error('The method "parent" cannot be called.'); // 当前函数被调用的名字 function person(age) { this.age = age },则 age 被调用的就是 person 函数,就是获得 person 这个名字 var name = this.$caller.$name, // $owner 当前类对象, 获得当前类对象的父类对象 parent = this.$caller.$owner.parent, // 获得父类相同名字的方法 previous = (parent) ? parent.prototype[name] : null; if (!previous) throw new Error('The method "' + name + '" has no parent.'); // 父类的该同名函数,添加到当前子类中 return previous.apply(this, arguments); }; // 解除属性里对其余对象的引用 // 这个解除的例子,能够看 http://hmking.blog.51cto.com/3135992/675856 var reset = function(object){ for (var key in object){ var value = object[key]; switch (typeOf(value)){ case 'object': var F = function(){}; F.prototype = value; object[key] = reset(new F); break; case 'array': object[key] = value.clone(); break; } } return object; }; var wrap = function(self, key, method){ if (method.$origin) method = method.$origin; var wrapper = function(){ // 若是方法是是被保护的,或者这个方法没有 caller ,就不能被调用 if (method.$protected && this.$caller == null) throw new Error('The method "' + key + '" cannot be called.'); var caller = this.caller, current = this.$caller; this.caller = current; this.$caller = wrapper; // 将 method 绑定到当前对象中 var result = method.apply(this, arguments); this.$caller = current; this.caller = caller; return result; // 经过extend ,把当前函数的属性附加到 self 里去 }.extend({$owner: self, $origin: method, $name: key}); return wrapper; }; var implement = function(key, value, retain){ // Mutators 的 key 只有 Extends 和 Implements if (Class.Mutators.hasOwnProperty(key)){ value = Class.Mutators[key].call(this, value); if (value == null) return this; } if (typeOf(value) == 'function'){ // 隐藏的方法子类就不要再继承使用了 // $hidden 和 $protected 去看函数那章 if (value.$hidden) return this; this.prototype[key] = (retain) ? value : wrap(this, key, value); } else { // merge 应该是同名的函数,这样就直接添加进去就好 Object.merge(this.prototype, key, value); } return this; }; // 为了将父类的的属性继承到子类,会使用中间变量,将父类传递给中间变量,再经过中间变量传递给子类 var getInstance = function(klass){ // 谁知当前当前类正在构建 klass.$prototyping = true; var proto = new klass; // 这里就删除 $prototyping ,也就是构建的过程就是上面这一行咯 delete klass.$prototyping; return proto; }; // 这里有 overloadSetter ,因此,多是 Class.implement 方法,来给类额外添加函数的 Class.implement('implement', implement.overloadSetter()); Class.Mutators = { // 传给 extends 的参数是 parent Extends: function(parent){ // 指向当前类的父类是 parent 参数 this.parent = parent; // 使用 getInstance 获得父类的所有方法 this.prototype = getInstance(parent); }, Implements: function(items){ Array.convert(items).each(function(item){ var instance = new item; for (var key in instance) implement.call(this, key, instance[key], true); }, this); } }; })(); /* Extends 实际上是分两部分,使用 Extends 的时候,是把父类的全部属性和方法,经过 getInstance 来附加到当前类中 而后当前类的方法中,可使用 this.parent(args) 方法,来把父类的同名方法加载进来 Implements 方法中没有指代 this.parent = parent ,因此若是当前类写了和父类同名的方法,就会覆盖父类的方法 Implements 只是给当前类添加更多的方法 */
JS
面向对象系列app