Где в Рубиниусе реализованы миксины? - PullRequest
3 голосов
/ 08 октября 2011

Где в источнике Rubinius находится код, который отвечает за включение модулей? (В частности, чтобы разместить модуль как суперкласс класса объекта.)

1 Ответ

8 голосов
/ 08 октября 2011

Если вы посмотрите на документацию для 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.

...