2010-03-18 23 views
1

我需要擴展一個封裝在閉包中的類。這個基類是以下內容:閉包對象的繼承和方法的重寫

var PageController = (function(){ 

    // private static variable 
    var _current_view; 

return function(request, new_view) { 
    ... 

    // priveleged public function, which has access to the _current_view 
    this.execute = function() { 
     alert("PageController::execute"); 
    } 

} 
})(); 

繼承是使用下面的函數實現:

function extend(subClass, superClass){ 
var F = function(){ 
}; 
F.prototype = superClass.prototype; 
subClass.prototype = new F(); 
subClass.prototype.constructor = subClass; 
subClass.superclass = superClass.prototype; 
StartController.cache = ''; 


if (superClass.prototype.constructor == Object.prototype.constructor) { 
    superClass.prototype.constructor = superClass; 
} 
} 

我的子類的PageController:

var StartController = function(request){ 
    // calling the constructor of the super class 
    StartController.superclass.constructor.call(this, request, 'start-view'); 
} 
// extending the objects 
extend(StartController, PageController); 

// overriding the PageController::execute 
StartController.prototype.execute = function() { 
alert('StartController::execute'); 
} 

繼承工作。我可以從StartController的實例調用每個PageController的方法。但是,方法覆蓋不起作用:

var startCont = new StartController(); 
startCont.execute(); 

警報「PageController :: execute」。 我應該如何重寫此方法?

+0

爲什麼使用PageController的閉包?它看起來像_current_view也可以在構造函數中聲明。 – Alsciende

回答

2

它不工作,因爲StartController電話PageController這增加了execute屬性爲你的對象,所以不使用的StartController.prototypeexecute財產。

爲了您的壓倒一切的工作,你必須要麼:

1)定義PageController.prototype.executePageControllerexecute方法。它不起作用,因爲該功能無法訪問_current_view

2)在對象構造定義StartController.execute

var StartController = function(request){ 
    // calling the constructor of the super class 
    StartController.superclass.constructor.call(this, request, 'start-view'); 
    // overriding the PageController::execute 
    this.execute = function() { 
     alert('StartController::execute'); 
    } 
} 
// extending the objects 
extend(StartController, PageController); 

編輯:

所以,你要爲StartController.execute訪問_current_view,這是不可能的,只要_current_view是一個封閉的一部分StartController是不屬於。您可能必須這樣進行:

(function() { 
    var _current_view; 
    window.PageController = function(request, new_view) { 
    ... 
    this.execute = function() { ... } 
    } 

    window.StartController = function(request) { 
    StartController.superclass.constructor.call(this, request, 'start-view'); 
    this.execute = function() { ... } 
    } 
    extend(StartController, PageController); 

}() 
var startCont = new StartController(); 
startCont.execute(); 

如果你想要某種保護的行爲,你可能會想嘗試這種伎倆:

(function() { 
    var token = {}; 

window.Class1 = function() { 
    this.protectedMethod = function(tok) { 
     if(tok != token) return; // unauthorized 
     ... 
    } 
    } 

    window.Class2 = function() { 
    new Class1().protectedMethod(token); // access granted 
    } 
})() 

new Class1().protectedMethod(); // access denied 

有在JavaScript中的包沒有這樣的事情,所以你的可能性是有限的。您當然不能在不屬於同一腳本的函數/對象/構造函數中擁有任何類型的特權。至少沒有我知道的。除了查詢服務器的某種授權外。

+0

第二種方法無法訪問_current_view。但是,現在我不確定我的封閉設計決定是否正確。 _current_view是靜態的和私有的,但我需要從子類訪問_current_view,這更像是一個「受保護的」行爲。我可以爲_current_view創建公共訪問器方法,但它可以讓每個人修改_current_view,並且我想避免這種情況。 順便說一下,有沒有什麼技術來模擬「保護」變量? – bobikk

+0

是的,有。我會在這一點上更新我的答案以幫助你。但我現在的答案符合你的問題,因爲你沒有要求StartController訪問_current_view,對吧? – Alsciende

+0

謝謝你真正詳細和全面的答案。我認爲,我開始更好地理解JavaScript的概念。謝謝! – bobikk