TypeScript: абстрагирование / извлечение части функциональности класса без использования расширений - PullRequest
0 голосов
/ 05 мая 2020

Допустим, у меня есть класс с различными функциональными областями:

export class TreeTable extends someOtherClass {
    constructor(){
       super.constructor();
    }
   //========= area 1 of functionality ====
   itemRightClick(){this.contextMenu();}
   contextMenu(){
     // open file or folder context menu
   }
   fileContextMenu(){}
   folderContextMenu(){}

   //========= area 2 of functionality ====
   loadData(){}
   subScribeStuff(){}
   unsusbscribeStuff(){}

   //======== area 3 SomeOtherClasses functionality
   someOtherClassMethod_1(){
   this.someOtherClassMethod();
   super.someOtherClassMethodTwo();
  }
}

И я хочу извлечь абстрактную область-1 во внешний класс.

class ContextMenu {
   constructor(){}
    //========= area 1 of functionality ====
   itemRightClick(){this.contextMenu();}
   contextMenu(){
     // open file or folder context menu
   }
   fileContextMenu(){}
   folderContextMenu(){}
}
export class TreeTable extends someOtherClass {

    constructor(){
       super.constructor();
    }
   //======== AREA 1
   // DECORATE THIS CLASS WITH class ContextMenu AND ADD ITS METHODS
   //========= area 2 of functionality ====
   loadData(){}
   subScribeStuff(){}
   unsusbscribeStuff(){}

   //======== area 3 SomeOtherClasses functionality
   someOtherClassMethod_1(){
   this.someOtherClassMethod();
   super.someOtherClassMethodTwo();
  }
}

выглядит как-то этого должно быть просто достичь. Не ищу наследства, а украшения. Я видел, что декораторы (@) для этого не используются.

1 Ответ

1 голос
/ 05 мая 2020

Прежде всего, важно отметить, что, в отличие от строго OOP языков, JS не поддерживает абстрактные классы.

Однако с вашей текущей иерархией классов невозможно будет выбрать какие бы члены вы ни хотели от класса X, и передать его классу Y, не расширяя весь класс X.

Принимая во внимание парадигмы OOP и SOLID, вам нужно немного подумать о моделировании ваших объектов по-другому. Учитывая эти различные «области» функциональности, ваш класс становится ответственным за множество различных обязанностей (загрузка данных, подписка и отмена подписки, а также выполнение действий с контекстными меню), которые могут быть разделены либо конкретно в их собственных определениях классов, либо абстрактно путем составления Интерфейсы TypeScript.

Особое внимание уделяется функциональным областям, 1-3, у вас есть следующие варианты:

1. Изолируйте каждую область связанных функций и переместите эти группы в их собственные классы

class Area1 {
  ...
}

class Area2 {
  ...
}

class Area3 {
  ...
}

Вы можете добавить экземпляры Area1, Area2 или Area3 в качестве членов TreeTable или создать иерархию типов:

2. Используйте интерфейсы TypeScript для express членов ваших классов

interface IArea1 {
  ...
}

interface IArea2 {
  ...
}

interface IArea3 {
  ...
}

, затем вы можете выбрать, какую структуру должен иметь ваш конкретный тип, реализовав столько интерфейсов, сколько вам нравится:

export class TreeTable extends someOtherClass implements IArea1, IArea3 {
  // implement members for IArea1
  // implement members for IArea2
}

Or construct an ITreeTable interface from other interfaces: 
interface ITreeTable extends IArea1, IArea3 {
  // any other functionality specific to ITreeTable
}

Then you class definition changes accordingly:
export class TreeTable extends someOtherClass implements ITreeTable {
  // implement members for IArea1
  // implement members for IArea2
}

3. Fore go OOP и использование обычных JavaScript объектов; однако это немного драматичное c изменение, если ваша кодовая база в значительной степени объектно-ориентирована, плюс потребитель вашего API тоже должен будет измениться

const area1 = {
  // some functions
}

const area2 = {
  // some other functions
}

const area3 = {
  // more functions
}

const treeTable = {
  ...area1,
  ...area3
}

Вы все равно можете использовать абстрактные интерфейсы здесь:

interface ITreeTable extends IArea1, IArea3 {
  // any other functionality specific to ITreeTable
}

const treeTable: ITreeTable = {
  // add all the necessary interface members
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...