實現類的步驟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