【问题标题】:Access child class static member from a base class static member从基类静态成员访问子类静态成员
【发布时间】:2018-10-05 05:01:18
【问题描述】:

Here 是如何从基类非静态成员访问子类静态成员。

我想知道:它是否也可以来自基本静态成员?

我尝试了以下不起作用的代码 (Stackblitz):

export class EntityBase {
    // Base static property initialized using a child static memeber
    public static TypeName: string = (EntityBase as any).$typeName;

    public static StaticBaseMethod(): string {
      return (EntityBase as any).$typeName;
    }

    public static seeIfWorks(): any {
        return {
          field: EntityBase.TypeName,
          method: EntityBase.StaticBaseMethod()
        };
    }
}

export class Entity extends EntityBase {
    public static $typeName: string = "CoolChildType";
}

// Test call
this.test = EntityBase.seeIfWorks()

seeIfWorks() 方法返回的对象的两个属性都是undefined

问题是不能从基本静态成员直接访问子构造函数。到目前为止,我唯一的方法是将其显式传递给基本静态方法,但也许已经有针对此问题的语言集成解决方案。

【问题讨论】:

    标签: typescript oop inheritance static


    【解决方案1】:

    这个类层次有几个问题:

    • 仅静态类通常是 JavaScript/TypeScript 中的反模式
    • this.test = EntityBase.seeIfWorks() 示例中使用EntityBase 代替Entity,不涉及子类
    • 类构造函数在EntityBase中被硬编码为EntityBase,不可能这样引用Entity
    • TypeName 被硬编码为 EntityBase.$typeName,它不能引用 Entity.$typeName 而不在子类中重新定义它或使用 getter
    • EntityBase 在使用时没有 $typeName 属性,这是类设计错误。应该以任何方式定义属性
    • EntityBase 可以直接使用,但由于未定义$typeName 不应该使用。如果它是基类,它应该是abstract。这并不妨碍它使用静态方法(必要时它们可以包含运行时检查),而是指定了它的用途。

    应该是:

    export abstract class EntityBase {
        static $typeName?: string;
    
        static get TypeName(): string {
           if (this === EntityBase) throw 'Cannot be accessed';
           return this.$typeName;
        }
    
        static StaticBaseMethod(): string {
           if (this === EntityBase) throw 'Cannot be accessed';
           return this.$typeName;
        }
    
        static seeIfWorks(): any {
           if (this === EntityBase) throw 'Cannot be accessed';
           return {
              field: this.TypeName,
              method: this.StaticBaseMethod()
            };
        }
    }
    
    export class Entity extends EntityBase {
        static $typeName: string = "CoolChildType";
    }
    

    【讨论】:

      【解决方案2】:

      对我的问题的简单回答是:您实际上可以从基类静态成员中引用子静态成员。这可以通过this 关键字而不是基类名称来完成(感谢@estus 在他的answer 中展示它)。

      作为一名主要来自基于类的语言背景的开发人员,我错过了在 TypeScript 的静态成员中使用 this 的选项。

      因此,我的问题中的示例可以通过将基类名称替换为 this 来解决,只要我们想引用子类静态成员:

      export class EntityBase {
          // Static initializer doesn't work for the purpose, since it's called once during first usage of base class. Use static getter instead (below).
          // public static TypeName: string = (EntityBase as any).$typeName;
      
          // Static getter
          public static get TypeName(): string {
             return (this as any).$typeName;
          }
      
          public static StaticBaseMethod(): string {
            return (this as any).$typeName;
          }
      
          public static seeIfWorks(): any {
              return {
                field: this.TypeName,
                method: this.StaticBaseMethod()
              };
          }
      }
      

      另外,我在测试时指的是基类而不是子类。正确的做法是:

      // Test call
      this.test = Entity.seeIfWorks()
      

      查看更新后的Stackblitz,其中我还为两个派生类添加了一个测试用例。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-08-07
        • 2011-04-18
        相关资源
        最近更新 更多