Введение

Класс в объектно-ориентированных языках программирования – это концепция программирования.

В объектно-ориентированных языках программирования миксин (или "смесь") используется для решения "алмазной проблемы" или для обхода отсутствия поддержки множественного наследования в языке. Миксин также можно рассматривать как интерфейс с реализованными методами. Этот подход является примером реализации принципа инверсии зависимостей.

История

Миксины впервые появились в объектно-ориентированной системе Flavors, разработанной Говардом Кэнноном, которая представляла собой подход к объектной ориентации, использовавшийся в Lisp Machine Lisp. Название было вдохновлено магазином Steve's Ice Cream Parlor в Сомервилле, штат Массачусетс: владелец предлагал базовые вкусы мороженого (ваниль, шоколад и т.д.) и добавлял в них различные ингредиенты (орехи, печенье, шоколадную глазурь и т.д.), называя получившийся продукт "mix in" – его собственным зарегистрированным товарным знаком в то время.

Определение

Миксины — это концепция языка программирования, позволяющая разработчику добавлять код в класс. Миксин-программирование — это стиль разработки программного обеспечения, при котором отдельные блоки функциональности создаются в классе, а затем включаются в другие классы. Класс-миксин выступает в роли родительского класса, содержащего необходимую функциональность. Подкласс может затем наследовать или просто повторно использовать эту функциональность, но не для целей специализации. Обычно миксин предоставляет желаемую функциональность дочернему классу, не создавая жёсткой, однозначной связи типа "является". Важное отличие между миксинами и наследованием заключается в том, что дочерний класс может по-прежнему наследовать все возможности родительского класса, но при этом семантика, подразумевающая, что дочерний класс "является разновидностью" родительского, не обязательно должна соблюдаться.

Преимущества

Он предоставляет механизм, позволяющий реализовать множественное наследование, давая одному классу возможность использовать общую функциональность из нескольких классов, но без присущей множественному наследованию сложности. Повторное использование кода: миксины полезны, когда программисту необходимо разделить функциональность между разными классами. Вместо многократного повторения одного и того же кода, общую функциональность можно просто сгруппировать в миксин и затем включить в каждый класс, которому она необходима. Миксины позволяют наследовать и использовать только нужные функции из родительского класса, а не обязательно все его функции.

Реализация

В Simula классы определяются в блоке, в котором атрибуты, методы и инициализация класса определены вместе; таким образом, все методы, которые могут быть вызваны для класса, определены вместе, и определение класса завершено. В Flavors миксин – это класс, из которого другой класс может наследовать определения слотов и методы. Миксин обычно не имеет прямых экземпляров. Поскольку Flavor может наследовать от более чем одного другого Flavor, он может наследовать от одного или нескольких миксинов. Следует отметить, что оригинальные Flavors не использовали обобщенные функции. В New Flavors (преемнике Flavors) и CLOS методы организованы в "обобщенные функции". Эти обобщенные функции – это функции, которые определяются в нескольких вариантах (методах) посредством диспетчеризации по классу и комбинаций методов. CLOS и Flavors позволяют методам миксинов добавлять поведение к существующим методам: методы :before и :after, а также whoppers и wrappers в Flavors. CLOS добавил методы :around и возможность вызова затененных методов через So. Например, миксин блокировки потока может добавлять блокировку вокруг существующих методов класса потока. В Flavors для этого можно было бы написать wrapper или whopper, а в CLOS – использовать метод :around. И CLOS, и Flavors позволяют повторное использование посредством комбинаций методов. Методы :before, :after и :around являются особенностью стандартной комбинации методов. Предоставляются и другие комбинации методов. Примером является комбинация методов +, где результирующие значения каждого из применимых методов обобщенной функции арифметически складываются для вычисления возвращаемого значения. Это используется, например, с миксином границы для графических объектов. Графический объект может иметь обобщенную функцию ширины. Миксин границы добавляет границу вокруг объекта и имеет метод для вычисления его ширины. Новый класс "кнопка с границей" (который является одновременно графическим объектом и использует миксин границы) будет вычислять свою ширину, вызывая все применимые методы ширины – посредством комбинации метода +. Все возвращаемые значения складываются, формируя общую ширину объекта. В статье, представленной на OOPSLA 90, Гилад Брача и Уильям Кук переосмыслили различные механизмы наследования, обнаруженные в Smalltalk, Beta и CLOS, как специальные формы наследования миксинов.

На других языках

В языке веб-контента Curl используется множественное наследование, поскольку классы, не имеющие экземпляров, могут реализовывать методы. Распространенные миксины включают все управляемые стилем ControlUI, наследующие от SkinnableControlUI, объекты-делегаты пользовательского интерфейса, которым требуются выпадающие меню, наследующие от StandardBaseDropdownUI, а также явно названные классы миксинов, такие как FontGraphicMixin, FontVisualMixin и NumericAxisMixin. Версия 7.0 добавила доступ к библиотекам, чтобы миксины не обязательно находились в одном пакете или были публичными абстрактными классами. Конструкторы Curl – это фабрики, облегчающие использование множественного наследования без явного объявления интерфейсов или миксинов.

Интерфейсы и особенности

Java 8 представляет новую функцию в виде методов по умолчанию для интерфейсов. По сути, это позволяет определить метод в интерфейсе, что особенно полезно, когда необходимо добавить новый метод в интерфейс после того, как настройка программирования классов, реализующих этот интерфейс, уже завершена. Добавление новой функции в интерфейс обычно требует реализации этого метода во всех классах, использующих интерфейс. Методы по умолчанию решают эту проблему, поскольку их можно добавлять в интерфейс в любое время, и они уже содержат реализованную структуру, которую затем используют соответствующие классы. Таким образом, методы по умолчанию добавляют возможность применения концепции миксинов в Java. Интерфейсы, в сочетании с аспекто-ориентированным программированием, также могут создавать полноценные миксины в языках, поддерживающих такие возможности, как C# или Java. Кроме того, благодаря использованию шаблона интерфейса-маркера, обобщенного программирования и методов расширения, C# 3.0 позволяет имитировать миксины. С Dart 2.7 и C# 3.0 появились методы расширения, которые можно применять не только к классам, но и к интерфейсам. Методы расширения предоставляют дополнительную функциональность существующему классу, не изменяя сам класс. В этом случае можно создать статический вспомогательный класс для конкретной функциональности, определяющий методы расширения. Поскольку классы реализуют интерфейс (даже если сам интерфейс не содержит никаких методов или свойств для реализации), они также будут использовать все методы расширения. C# 8.0 добавляет функцию методов интерфейса по умолчанию. ECMAScript (в большинстве случаев реализованный как JavaScript) не нуждается в имитации композиции объектов путем последовательного копирования полей из одного объекта в другой. Он изначально поддерживает композицию объектов на основе трейтов и миксинов с помощью функциональных объектов, реализующих дополнительное поведение, которое затем делегируется объектам, нуждающимся в этой новой функциональности, посредством вызова или применения.