簡體   English   中英

Typescript:super.super 調用受保護的方法

[英]Typescript: super.super call on a protected method

我正在嘗試擴展/覆蓋 class 中的受保護方法,我們將ChildClass稱為 class 庫的受保護覆蓋方法tapNodeParentClass中,其方法調用superGrandParentClass tapNode

我想覆蓋行為,以便ChildClass可以在從ParentClass擴展時調用grandParentClass

為了澄清,我們有

export class ChildClass extends ParentClass {
  override tapNode(node?: TreeNode): void {
    custom_stuff();
    super.super.tapNode(node); //What I ideally want to do but can't
}
export class ParentClass extends ChildClass {
  override tapNode(node?: TreeNode): void {
    [ ...
      inline class-specific code
    ... ]
    super.tapNode(node);
}
export class GrandParentClass extends ParentClass {
  override tapNode(node?: TreeNode): void {
    [ ...
      inline class-specific code
    ... ]
    super.tapNode(node)
}

到目前為止我看過的一些方法:

  • 我知道如何使用prototype方法,但這似乎只適用於公共方法,而不是受保護的方法。 (有關該方法的更多信息,請參閱TypeScript super.super 調用

  • 我知道 mixins 和 ts-mixer,但這似乎只有在有唯一方法名稱的情況下才有效,因為您正在組合類。 (見Typescript:如何擴展兩個類?

  • 我知道如果將特定於類的代碼放入它自己的方法中,則覆蓋它的想法,但這僅適用於將代碼分離到它自己的方法中,而不是當它內聯時。 以 https://stackoverflow.com/a/56536651/314780為例)。

  • 我知道您通常不想這樣做!

如您所見, class (和 ECMAScript,至少在撰寫本文時)中的 class inheritance 不支持此用例。

您還發現,一種可能的解決方法是回退到底層prototype 但是,對protected的方法執行此操作會引發 TypeScript 錯誤(正如您所指出的,TS 僅允許對public方法執行此操作)。

話雖如此,發出的 JS 代碼仍然包含prototype上的protected (甚至是private !)方法,因為可見性修飾符僅在 TS 級別

與 TypeScript 類型系統的其他方面一樣, privateprotected 僅在類型檢查期間強制執行

這意味着 JavaScript 運行時構造(如in或簡單屬性查找)仍然可以訪問privateprotected成員

因此,忽略 TS 錯誤,運行時按預期工作:

class GrandParentClass {
    protected tapNode(node?: TreeNode): void {
        /* ...
          inline class-specific code
        ... */
        console.log("GrandParent", node)
    }
}

class ParentClass extends GrandParentClass {
    override tapNode(node?: TreeNode): void {
        /* ...
          inline class-specific code
        ... */
        console.log("Parent", node)
        super.tapNode(node);
    }
}

class ChildClass extends ParentClass {
    override tapNode(node?: TreeNode): void {
        //custom_stuff();
        //super.super.tapNode(node); //What I ideally want to do but can't

        console.log("Child", node)

        // @ts-ignore In order to break the class inheritance contract,
        // we have to break the TS visibility modifier contract as well...
        GrandParentClass.prototype.tapNode.call(this, node)
        //                         ~~~~~~~ Error: Property 'tapNode' is protected and only accessible through an instance of class 'ChildClass'. This is an instance of class 'GrandParentClass'.
    }
}

new ChildClass().tapNode("some tree node")

type TreeNode = string 

...正確輸出:

[LOG]: "Child",  "some tree node" 
// (No Parent log)
[LOG]: "GrandParent",  "some tree node" 

游樂場鏈接

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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