簡體   English   中英

如何在基類方法中調用子類方法?

[英]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
  }
}

游樂場鏈接

arg1 類型

您的類並不都共享相同的簽名,因為它們對於傳遞給WriteStuff的第一個參數arg1都有不同的類型。 您很可能希望根據arg1的類型或其他值使用通用 class

如果SubClass1ItemSubClass2Item不擴展Item那么你絕對需要一個通用的 class 因為子類中WriteStuff的實現不能分配給基類。

如果他們確實擴展了Item ,那么當前設置不會出現 typescript 錯誤。 但是,當您從BaseClass中的GetOptions()調用this.WriteStuff時,可能會出現運行時錯誤。 BaseClass如何知道它擁有的Item是否可分配給SubClass1SubClass2中預期的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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM