В ruby причина, по которой миксины не являются множественным наследованием, заключается в том, что комбинирование методов миксина - это разовая вещь. Это не будет такой большой проблемой, за исключением того, что модули и классы Ruby открыты для модификации. Это означает, что если вы смешаете модуль с вашим классом, а затем добавите метод к модулю, метод не будет доступным для вашего класса; где, если бы вы сделали это в обратном порядке, это было бы.
Это похоже на заказ мороженого. Если вы получите в качестве своих миксинов шоколадные обсыпки и кусочки ириски и уйдете со своим конусом, то какой у вас конус мороженого не изменится, если кто-то добавит разноцветные обсыпки в корзину для обсыпки шоколада в магазине мороженого. Ваш класс, конус мороженого, не изменен, когда модуль mixin, мусорное ведро, является. Следующий человек, который будет использовать этот миксин-модуль, увидит изменения.
Когда вы include
модуль в ruby, он вызывает Module#append_features
на этом модуле, который добавляет копию методов этого модуля один раз.
Множественное наследование, насколько я понимаю, больше похоже на делегирование. Если ваш класс не знает, как что-то сделать, он спрашивает своих родителей. В среде открытого класса родители класса могли быть изменены после создания класса.
Это похоже на отношения между родителями и детьми. Ваша мать, возможно, научилась жонглировать после вашего рождения, но если кто-то попросит вас жонглировать, и вы попросите ее либо: показать вам, как (скопируйте это, когда вам это нужно), либо сделать это для вас (чистое делегирование), тогда она Вы сможете в этот момент, даже если вы были созданы до того, как ее способность жонглировать была.
Возможно, вы могли бы изменить модуль ruby 'include', чтобы он действовал больше как множественное наследование, изменив Module#append_features
, чтобы сохранить список включений, а затем обновить их с помощью обратного вызова method_added
, но это будет Значительно отличается от стандартного Ruby и может вызвать серьезные проблемы при работе с чужим кодом. Возможно, вам лучше создать метод Module#inherit
, который будет вызывать include
и обрабатывать делегирование.
Что касается примера из реального мира, Enumerable
потрясающий. Если вы определите #each
и включите в свой класс Enumerable
, то это даст вам доступ к целому ряду итераторов, без необходимости кодировать каждый из них.