smartjs 0.2 OOP講解 - Klass 類繼承

SmartJS2.0加入OOP的功能。OOP包括klass與factory兩個對象。promise

Klass 類繼承

與其餘的類繼承相比,smartjs使用了執行指針的概念(後面例子中會介紹),另外提供base基類和初始化控制的擴展功能。閉包

首先來看看接口:oop

  var _klass = st.klass(name, prop, parent, config);
    //new _klass() 與 _klass()效果相同,實現了自初始化功能更
    var obj = new _klass();

 

name : 類名測試

prop : 類屬性&方法this

parent :[可選],父類對象spa

config :[可選],類配置參數,作動態擴展使用;後續版本會加入內容;代理

注意自初始化方法爲:klassInit,在實例化時執行指針

實例化類後,對象會具備如下方法和屬性:code

//獲取基類對象
obj.getBase(baseName);
對象


//執行基類對象
obj.callBase(fnName, baseName, args);


//對象擴展方法
obj.extend(prop);


//父類對象
obj._$super


//類標示
obj._$klass : bool


//類名
obj._$kName : string


//繼承鏈
obj._$inheirts : array

 

此外兩種全局擴展方式:

1. 基於原形鏈的基類擴展,使用st.conf('oop-KlassBase'),能夠取到基類對象進行擴展

2. 在類初始化時,對實例化的對象進行擴展,能夠使用st.onKlassInit對象進行添加擴展方法。

st.onKlassInit 是promiseEvent對象,參數爲:obj,conf

  obj:類對象

  conf:即klass定義的時候的conf

 

 

代碼示例

基礎

 var user = st.klass("user", {
            klassInit: function(name) {
                this.name = name;
            },
            say: function(text) {
                return this.name + ',' + text;
            }
        });

             var user1 = new user('roy'),
                //執行方法與實例化等效
                user2 = user('tracy');

        expect(user1.name).toBe('roy');
        expect(user1.say('hello')).toBe('roy,hello');
        expect(user2.name).toBe('tracy');
        expect(user2.say('hello')).toBe('tracy,hello');

 

綜合例子

var user1 = st.klass("user1", {
            name: 'user1',
            //自初始化方法爲:klassInit,在實例化時執行
            klassInit: function() {}
        }, user);

        //繼承測試
        it("inheirt", function() {

            var roy = user1('roy');

            expect(roy.name).toBe('user1');
            expect(roy.say('hello')).toBe('user1,hello');
        })

        //調用父類測試
        it("klassBase - callBase", function() {
            var roy = user1();
            roy.callBase('klassInit', ['roy']);
            expect(roy.name).toBe('roy');
        })

        //擴展例子
        it("klassBase - extend", function() {
            var roy = user1();
            roy.extend({
                say: function() {
                    return "extend";
                }
            });

            expect(roy.say()).toBe('extend');
            expect(roy.callBase('say', ['extend'])).toBe("user1,extend");
        })

 

多級繼承例子。在多級繼承中有一種場景每一個子類方法都會調用父類的方法,而方法中又會使用到當前對象的屬性,則問題就來了;

若是是採用的parent.xxx而後傳遞this下的屬性值過去,則沒太大的問題。backbone就採用的這種。

另外像base.js直接改寫原始方法,將父對象封入閉包中,也無問題。只是這種限制比較大,只能調用父類的同名方法。

而dojo採用的是this.parent.xxx.call(this)的方式,則就會悲劇了,死循環就來了。

致使這樣的緣由就是將this帶入parent方法後,父類又執行this.parent。而這是this則是子類的對象,那麼方法就只會不停的調用parent的方法。

有興趣的朋友能夠下去看下,項目上面使用的繼承會出現此問題。若是有更好的方案,但願能分享。

 

smart採用類繼承的方式與dojo比較相似,可是調用父類方法由callBae這個方法來代理,同時使用指針來記錄方法的執行軌跡,這樣保證了從子到根的各級調用。

var user = st.klass("user", {
                klassInit: function(name) {
                    this.name = name;
                },
                say: function(text) {
                    return this.name + ',' + text;
                }
            })

            var user2 = st.klass('user2', {
                say: function(text) {
                    return this.callBase('say', [text]) + "-lv2";
                }
            }, user);

            var user3 = st.klass('user3', {
                say: function(text) {
                    return this.callBase('say', [text]) + "-lv3";
                }
            }, user2);

            var user4 = st.klass('user4', {
                say: function(text) {
                    return this.callBase('say', [text]) + "-lv4";
                }
            }, user3);

            var roy = new user4('roy');
            expect(roy._$inheirts + '').toBe('user4,user3,user2,user');
            //依次執行到根,正確將當前的this對象的值輸出
            expect(roy.say('hello')).toBe('roy,hello-lv2-lv3-lv4');

            //從3級開始執行
            expect(roy.callBase('say', ['hello'])).toBe("roy,hello-lv2-lv3");

            //指定從user開始執行
            expect(roy.callBase('say', 'user', ['hello'])).toBe("roy,hello");

            //上向略過2級執行
            expect(roy.callBase('say', 2, ['hello'])).toBe("roy,hello-lv2");
相關文章
相關標籤/搜索