![](/img/trans.png)
[英]Workaround for calling private method in baseclass from subclass in JavaScript
[英]How do you call a subclass method in the baseclass method?
如果這個問題如此令人困惑,我很抱歉,我將嘗試盡可能簡單。
TLDR; 如何在 Typescript 基類中調用必須在子類中定義的子類的私有方法?
我有許多不同的 Typescript 子類,它們需要不同的代碼來做同樣的事情:寫入文件。
90% 的基本代碼是相同的,每個子類都有一些方法的具體實現。
因此,我采用了相同的代碼並將其放在基礎 class 中,但這會調用必須在子類上實現的方法,並且最好是私有的。
這是一個例子:
abstract class BaseClass {
constructor() { }
SetOptions() {
// Set the options
// Return the options
}
GetOptions() {
// Get the options
this.WriteStuff();
}
private WriteStuff(arg1: Item, arg2: number) {}
}
class SubClass1 extends BaseClass {
private WriteStuff(arg1: SubClass1Item, number: number) {
// Write stuff in the SubClass1 way
}
}
class SubClass2 extends BaseClass {
private WriteStuff(arg1: SubClass2Item, number: number) {
// Write stuff the SubClass2 way
}
}
SubClass1Item 和 SubClass2Item 實現了 Item 接口。
所有子類對 SetOptions 和 GetOptions 使用相同的代碼,但 WriteStuff 在每個子類中都有個性化的代碼,並且需要是私有的,因此它不會被其他開發人員意外調用。
Typescript 說我不能這樣做,因為“類型具有私有屬性'WriteStuff'的單獨聲明”。 並且 Typescript 不會讓我不在 BaseClass 中聲明該方法,因為那時我正在調用一個不存在但將存在於子類中的方法。
這可能嗎?
private
方法只能在 class 本身中訪問,不能在任何后代中訪問。 你不能有一個private abstract
方法,因為這是一個內在的矛盾——如果后代需要實現它,那么它就不是private
的。
您想使用protected
的修飾符。 根據文檔:
protected
修飾符的作用與private
修飾符非常相似,但聲明為protected
的成員也可以在派生類中訪問。
你想在你的BaseClass
中聲明所有的 concretions 必須實現一個WriteStuff()
方法。 這是一個abstract
方法,意味着它在BaseClass
中沒有實現,必須被覆蓋。
在您的后代中, WriteStuff
的實現必須受到protected
而不是private
。
abstract class BaseClass {
/* .... */
protected abstract WriteStuff(arg1: Item, arg2: number): void;
}
class SubClass1 extends BaseClass {
protected WriteStuff(arg1: SubClass1Item, number: number) {
// Write stuff in the SubClass1 way
}
}
您的類並不都共享相同的簽名,因為它們對於傳遞給WriteStuff
的第一個參數arg1
都有不同的類型。 您很可能希望根據arg1
的類型或其他值使用通用 class 。
如果SubClass1Item
和SubClass2Item
不擴展Item
那么你絕對需要一個通用的 class 因為子類中WriteStuff
的實現不能分配給基類。
如果他們確實擴展了Item
,那么當前設置不會出現 typescript 錯誤。 但是,當您從BaseClass
中的GetOptions()
調用this.WriteStuff
時,可能會出現運行時錯誤。 BaseClass
如何知道它擁有的Item
是否可分配給SubClass1
或SubClass2
中預期的Item
子類型? 這是 generics 可以提供幫助的地方。
我們基於變量ItemType
使BaseClass
成為泛型。 我們可以要求所有ItemType
變量擴展一個共享的基礎Item
,但我們不必這樣做。
子類本身不是通用類。 他們將使用他們需要的特定ItemType
擴展BaseClass
的一個版本。
abstract class BaseClass<ItemType extends Item> {
/* ... */
GetOptions(item: ItemType) {
// Get the options
this.WriteStuff(item, 5);
}
protected abstract WriteStuff(arg1: ItemType, arg2: number): void;
}
class SubClass1 extends BaseClass<SubClass1Item> {
protected WriteStuff(arg1: SubClass1Item, number: number) {
// Write stuff in the SubClass1 way
}
}
JavaScript 最近支持私有字段聲明,包括私有實例方法。 在那里,一種可能的方法是為基類的超級調用提供子 class 特定實現......
class BaseClass { // default implementation of private instance method. #writeStuff = () => void 0; constructor(writeStuff) { // at instantiation time, if appropriate, ... if (typeof writeStuff === 'function') { //... overwrite the default implementation. this.#writeStuff = writeStuff; } } // prototypal method... getOptions(...args) { //... with access to a private instance method. this.#writeStuff(...args); } setOptions() {/*... */} } class SubClass1 extends BaseClass { constructor() { const writeStuff = (...args) => // Write stuff in the SubClass1 way console.log(`SubClass1 [...args]: ${ [...args] }`); super(writeStuff); // do other things } } class SubClass2 extends BaseClass { constructor() { const writeStuff = (...args) => // Write stuff in the SubClass2 way console.log(`SubClass2 [...args]: ${ [...args] }`); super(writeStuff); // do other things } } const objA = new SubClass1; const objB = new SubClass2; objA.getOptions('foo', 'bar'); objB.getOptions('baz', 'biz');
.as-console-wrapper { min-height: 100%;important: top; 0; }
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.