从基类静态成员访问子类静态成员

时间:2018-04-24 20:12:09

标签: typescript oop inheritance static

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

问题是没有从基本静态成员直接访问子构造函数。我到目前为止唯一的方法是将它明确地传递给基本静态方法,但也许已经有针对这个问题的语言集成解决方案。

2 个答案:

答案 0 :(得分:0)

此类层次结构有几个问题:

  • static-only类通常是JavaScript / TypeScript中的反模式
  • EntityBase示例中使用
  • Entity代替this.test = EntityBase.seeIfWorks(),子类不参与
  • 类构造函数被硬编码到EntityBase中的EntityBase,无法以这种方式引用Entity
  • TypeName被硬编码为EntityBase.$typeName,如果不在子类中重新定义或使用getter,则无法引用Entity.$typeName
  • 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";
}

答案 1 :(得分:0)

我的问题的简单答案是:您实际上可以从基类静态成员引用子静态成员。这可以通过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,其中我还为两个派生类添加了一个测试用例。