2010-10-27 3 views
11

Мац якобы сказал «Примеси может делать почти все, что множественное наследование сделать, без сопутствующих недостатков» (Мац слов).»Каким образом включение модуля Ruby не является «множественным наследованием» и как стиль Ruby позволяет избежать проблем, связанных с множественным наследованием?

Прежде всего, почему включение модуля рубин не« множественное наследование? Мне кажется, там очень мало различий между модулями и классами. Тот факт, что вы не можете создать экземпляр модуля, не имеет значения, когда он используется в качестве суперкласса.

Я также знаю, что последовательное включение модуля образует единую цепочку наследования (не дерево), простирающуюся вверх от класс, но этого для меня недостаточно, чтобы отличить его от «множественного наследования», поскольку система множественного наследования Python также «линеаризует» цепь суперкласса (используя C3 algorithm) это просто, что процесс линеаризации Ruby значительно проще.

Итак, что именно отличает модули Ruby от смешанного наследования в языке, таком как Python? И почему аргументы, лежащие в основе внедрения Python алгоритма C3 MRO, применимы к Ruby? И если они применимы - почему Руби решил не применять этот алгоритм?

благодаря

+6

Вот хорошая статья по этому вопросу, посмотрите, отвечает ли он на ваш вопрос: http://www.artima.com/weblogs/viewpost.jsp?thread=246488 –

+0

@Mladen это абсолютно блестяще .... если вы добавите его в качестве правильного ответа, я приму 'it :) – horseyguy

ответ

3

Добавление этого от имени Младена в качестве фактического ответа, потому что я нашел его очень полезным, и я предполагаю, что ответы лучше индексируются для любых сумасшедших вещей, которые с ним делают.

Вот хорошая статья по этому вопросу, увидеть, если она отвечает на ваш вопрос: http://artima.com/weblogs/viewpost.jsp?thread=246488 - Младен Jablanović 28 '10 Октябрь в 18:23

0

Отъезд книги «Метапрограммирование Рубин» с прагматической Press. Он содержит очень подробное объяснение этого, таким образом, что его очень легко читать и понимать. http://pragprog.com/titles/ppmetr/metaprogramming-ruby

Я не могу ответить на твой вопрос, потому что я не знаю питона. но основы того, почему это не множественное наследование, - это то, что рубин вводит модуль в цепочку наследования, когда модуль включен или класс расширяется модулем.

class Foo 
    include Bar 
end 

module Bar 
end 

foo = Foo.new 

Это создает цепочку наследования, где foo является экземпляром Foo и Foo, наследуемым от Bar.

Это немного сложнее, чем просто это, и существуют правила для порядка, в котором происходит инъекция наследования. книга, на которую я ссылаюсь, объясняет это очень хорошо.

+0

Спасибо, хе-хе, но как вы думаете, вы могли бы более подробно изложить, что говорит книга? Примечание. Мне не нужно знать особенности того, как вводится модуль, а больше теория, почему они выбрали этот подход по сравнению с типичным методом множественного наследования и КАК он отличается от обычного подхода к ИИ. :) Извините, что спросила, но я не собираюсь покупать эту книгу (у меня уже слишком много, чтобы читать хе-хе). – horseyguy

+0

Я читал «Метапрограммирование рубинов», и я не знаю ответа на вопрос о баннире. –

0

Самое важное в рубине - это переписать предыдущие определения данных/функций с каждым включенным модулем.

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

Так пример кода, чтобы написать новый модуль (логически):

old_function = fun 
fun = define_new_function 
    do_you_staff 
    call old_function 

Вам не придется использовать старую функцию, хотя в большинстве случаев это полезно, но иногда проще переписать весь код.

Каждый включенный модуль будет создавать цепочку перезаписанных методов, поэтому проблем с множественным наследованием не будет, но порядок включения модулей становится более важным.

Этот метод также называется патчей обезьяны - термин широко используется в Ruby on Rails.

4

С МИ, многие проблемы, которые возникают, могут быть сведены к деталям реализации; вы не можете просто говорить о «множественном наследовании» вообще, не говоря о специфике. Поэтому я буду предполагать, что вы имеете в виду «множественное наследование C++», когда вы говорите «множественное наследование».

Наиболее распространенной проблемой с множественным наследованием является Diamond Problem. Если несколько суперклассов на одном уровне определяют один и тот же метод, как вы знаете, какой метод вызывается в подклассе?

С модулями на эту проблему легко ответить - последний включенный модуль всегда «выигрывает». Вы не можете включать несколько модулей «одновременно», как это можно сделать с классами на C++. Поэтому эта проблема никогда не возникает.

Тот факт, вы не можете создать экземпляр модуля не имеет значения, когда он используется в качестве суперкласса

Я почтительно не согласен.

Во-первых, модули никогда не используются в качестве суперклассов в рубине; только суперклассы.

Во-вторых, с множественным наследованием, зная точно, в каком порядке конструкторы (деструкторы!) Называются not a trivial matter. Тот факт, что модули ruby ​​не позволяют создавать экземпляры, полностью подавляет эту проблему.

+1

Спасибо, однако лучшим сравнением будет MI Python, а не C++. Я, с уважением, не согласен снова относительно включенных модулей и «суперклассов» :). Включенный модуль работает почти так же, как «суперкласс» в Ruby - это указатель суперкласса класса указывает на включенный модуль (точно так же, как он указывает на суперкласс). Кроме того, тот факт, что модули Ruby соответствуют правилу «последний включенный модуль всегда« выигрывает »,« можно рассматривать как просто алгоритм линеаризации, аналогичный линеаризации C3 Pythons, поэтому я не вижу, как это само по себе отличает его от MI. – horseyguy

+0

«почти» - это не то же самое, что «точно». Различия важны. Например, «super» не работает для модулей. Но в любом случае я не понимал, что это вопрос Питона. Думаю, я заслуживаю, чтобы -1:/ – kikito

+1

супер не работает для модулей? Да. – horseyguy