Автоматное программирование
- 1 year ago
- 0
- 0
При́месь ( англ. mix in ) — элемент языка программирования (обычно класс или модуль), реализующий какое-либо чётко выделенное поведение. Используется для уточнения поведения других классов, не предназначен для порождения самостоятельно используемых объектов .
В объектно-ориентированных языках программирования является способом реализации классов, отличным от широко используемых принципов, пришедших из языка программирования Simula . Механизм впервые реализован в . Преимуществом примесей является то, что повышая повторную используемость текстов программ , этот метод избегает многих проблем множественного наследования . Однако при этом метод накладывает свои ограничения.
В большинстве объектно-ориентированных языков, начиная с Simula , класс определяется атрибутами , методами , конструкторами и деструкторами как единое, тесно связанное целое. Определение класса обладает полнотой. Именно этот факт показался полезным Страуструпу и Эллис, которые на этом основании не стали реализовывать примеси в Си++ на уровне языка (Си++ разрабатывался как «совместимое расширение Си в сторону Симулы») [ источник не указан 4148 дней ] .
В языке с использованием примесей класс определяется только с атрибутами и параметрами, связанными с классом. Методы определяются в другом месте, как в Flavors и CLOS , и являются . Последние реализуются для различных типов посредством диспетчеризации.
Кроме Flavors и CLOS, примеси поддерживают следующие языки:
Пример на языке Ruby. Класс реализует простую концепцию возраста. Значение возраста хранится во внутренней переменной « age », которая открыта для записи и чтения. Для получения возможности сравнения возрастов класс реализует один оператор « <=> », а все остальные (больше, меньше, равно и т. д.) реализуются с использованием этого метода во включаемом модуле « Comparable ».
class Age
include Comparable
attr_accessor(:age)
def <=>(cmp)
@age <=> cmp.age
end
end
Пример демонстрирует создание объектов и использование «подмешанных» методов:
a, b = Age.new, Age.new
a.age = 10
b.age = 11
if a < b then puts "a меньше, чем b." end
Примеси можно рассматривать как неполную реализацию множественного наследования , его частный вид. В языках, поддерживающих множественное наследование, примеси могут легко эмулироваться. Например, в C++ следующий шаблон может использоваться для добавления в класс оператора « != » при наличии оператора « == »:
template <typename T> struct AddNoEq {
virtual bool operator==(const T &cmp) const = 0;
bool operator!=(const T &cmp) const {
return !static_cast<const T*>(this)->operator== (cmp);
}
};
Простой пример использования для класса комплексных чисел :
#include <iostream>
struct Complex : public AddNoEq<Complex> {
Complex(int re, int im): re_(re), im_(im) { }
virtual bool operator==(const Complex& cmp) const {
return cmp.re_ == this->re_ && cmp.im_ == this->im_;
}
// ...
private:
int re_, im_;
};
int main()
{
Complex a(1, 2), b(2, 3);
if (a != b)
std::cout << "Так и должно быть" << std::endl;
return 0;
}
Данный метод в более развёрнутом виде используется в библиотеке « Boost operators».
Близкую к примесям функциональность предоставляют интерфейсы в языках вроде Java и C# , c тем отличием, что интерфейс только специфицирует поведение, но не предоставляет реализации (в Java с версии 1.8 в интерфейсе частичная реализация, C# вводит понятие «реализация по умолчанию» начиная с версии 8.0). Механизм может быть полезен только для представления полиморфизма . Другие классы, предоставляющие реализацию интерфейса, полезны для вынесения общей функциональности в единое место.
Совместно используя методы-расширения и интерфейсы , возможно реализовать функциональность примесей в C#.