Множественное наследование — это функция, при которой класс может расширять более одного базового класса.
Проблема
Что, если мы хотим создать разные компоненты пользовательского интерфейса, такие как «кнопка», «ввод», «элемент списка действий» и «пункт меню»? Все эти компоненты имеют разное поведение и внешний вид. Однако все они могут быть отключены, могут иметь базовый цвет, а последние два — общий базовый класс. Мы хорошие разработчики и хотим писать чистый и СУХОЙ код. Итак, давайте посмотрим, что мы можем сделать в этой ситуации.
Расширение
Допустим, у нас есть три класса, которые предоставляют три метода, и мы хотим создать четвертый класс, который будет предоставлять все эти три метода.
Наиболее логичным решением будет сделать что-то вроде этого:
Однако это не сработает. Typescript допускает расширение только одного базового класса. Итак, нам нужно продлевать их один за другим в цепочке.
Все работает, и с этим можно жить, но что, если в некоторых из полученных классов нам не нужен метод b
? Он у нас все равно будет, потому что класс C
расширяет класс B
и без него не будет метода a
из класса A
. Конечно, мы можем создавать комбинации классов, такие как класс AC
, которые будут расширять A
, а не расширять B
и так далее, но такой код очень быстро станет нечитаемым и непригодным для сопровождения.
Состав
Вместо расширения мы можем составить наши классы внутри полученного.
Это решение довольно хорошее и настоятельно рекомендуется, если вы создаете компоненты в Angular. Но и у него есть свои ограничения. Что, если некоторые из этих классов имеют свойства или геттеры, к которым мы хотим обращаться непосредственно в нашем классе D
? Или мы не хотим вызывать методы так долго?
Миксины
Typescript дает нам замечательный шаблон, позволяющий нам создать функцию, которая расширит базовый класс. Реализуем расширение классов A
и C
на D
. И пусть наш класс A
имеет защищенное свойство _propA
и геттер для него.
Прежде всего, нам нужно сделать некоторые приготовления. Нам нужно определить тип Constructor
и интерфейсы, которые реализуют классы A
и C
.
Теперь мы можем создать функцию миксина для класса A
.
Давайте разберемся, что здесь происходит. Функция mixinA
принимает в качестве аргумента анонимный класс и возвращает шаблон выражения класса, расширяющий класс, который мы предоставили в качестве аргумента. Внутри этого шаблона выражения мы определяем все свойства и методы, которые должны быть у класса A
.
Теперь давайте создадим миксин для класса C
.
А теперь давайте, наконец, создадим наш получившийся класс D
.
Вы можете видеть, что класс D
имеет все методы и свойства, унаследованные от классов A
и C
.
Потрясающий! А что, если мы хотим, чтобы наш класс D
имел базовый класс в дополнение к классам A
и C
? Единственное, что нам нужно сделать, это просто определить его и передать mixinA
в качестве аргумента.
Используя универсальный тип Constructor
, мы можем ограничить, какой тип мы можем предоставить как base
для функции миксина.
Заключение
Несмотря на ограничение JavaScript на расширение только одного класса, у нас есть способ решить проблему чисто и красиво. Мы можем использовать композиции или миксины в зависимости от поставленных перед нами задач.
Станьте компонуемым: создавайте приложения быстрее, как Lego
Bit – это инструмент с открытым исходным кодом для модульного и совместного создания приложений. Перейдите на компоновку, чтобы поставлять быстрее, более последовательно и легко масштабировать.
Создавайте приложения, страницы, пользовательский опыт и пользовательские интерфейсы как автономные компоненты. Используйте их, чтобы быстрее создавать новые приложения и возможности. Используйте любой фреймворк и инструмент в своем рабочем процессе. Делитесь, повторно используйте и сотрудничайте, чтобы строить вместе.
Помогите своей команде:
→ Совместное использование кода и повторное использование
→ Монорепо