Доступ к статическому члену дочернего класса из статического члена базового класса - PullRequest
0 голосов
/ 24 апреля 2018

Здесь - как получить доступ к статическому члену дочернего класса из нестатического члена базового класса.

Мне интересно: это также возможно из базового статического члена?

Я пробовал следующий код, который не работает ( 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 голосов
/ 25 апреля 2018

Простой ответ на мой вопрос: вы на самом деле можете ссылаться на дочерние статические члены из статического члена базового класса. Это можно сделать с помощью ключевого слова this вместо имени базового класса (спасибо @estus за демонстрацию этого в своем ответе ).

Как разработчик в основном из языков классов, я упустил возможность использования this в статических членах в TypeScript.

Итак, пример из моего вопроса можно исправить, заменив имя базового класса на 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 , где я также добавил тестовый пример для двух производных классов.

0 голосов
/ 25 апреля 2018

У этой иерархии классов есть несколько проблем:

  • статический класс обычно является антипаттерном в JavaScript / TypeScript
  • EntityBase используется вместо Entity в this.test = EntityBase.seeIfWorks() пример, дочерний класс не задействован
  • конструктор класса жестко задан в EntityBase в EntityBase, нет способа, как он может ссылаться на Entity таким образом
  • TypeName жестко запрограммирован на EntityBase.$typeName, он не может ссылаться на 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";
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...