Если вы посмотрите на документацию для Module#include
, вы обнаружите, что она делегирует Module#append_features
:
Вызывает Module.append_features
для каждого параметра в обратном порядке.
Документация для Module#append_features
, в свою очередь, описывает (очень кратко), как работает алгоритм Ruby mixin по умолчанию:
Когда этот модуль включен в другой, Ruby вызывает append_features
в этом модуле, передавая ему принимающий модуль в mod
. Реализация Ruby по умолчанию заключается в добавлении констант, методов и переменных модуля этого модуля в mod
, если этот модуль еще не был добавлен в mod
или одного из его предков. Смотрите также Module#include
.
Если вы посмотрите на Module#append_features
в исходном коде Rubinius , вы обнаружите, что это псевдоним для Module#include_into
:
# Called when this Module is being included in another Module.
# This may be overridden for custom behaviour. The default
# is to add constants, instance methods and module variables
# of this Module and all Modules that this one includes to +klass+.
#
# See also #include.
#
alias_method :append_features, :include_into
Итак, наконец, Module#include_into
является реальной сделкой:
# Add all constants, instance methods and module variables
# of this Module and all Modules that this one includes to +klass+
#
# This method is aliased as append_features as the default implementation
# for that method. Kernel#extend calls this method directly through
# Module#extend_object, because Kernel#extend should not use append_features.
def include_into(klass)
...
Ваш конкретный вопрос:
для точного размещения модуля как суперкласса класса объектов
ответ в этот цикл :
k = klass.direct_superclass
while k
if k.kind_of? Rubinius::IncludedModule
# Oh, we found it.
if k == mod
# ok, if we're still within the directly included modules
# of klass, then put future things after mod, not at the
# beginning.
insert_at = k unless superclass_seen
add = false
break
end
else
superclass_seen = true
end
k = k.direct_superclass
end
Часы для insert_at
.