2015-04-16 4 views

ответ

4

Вызов include M на верхнем уровне включает в свой модуль в Object:

module M 
    def m 
    "hello" 
    end 
end 

include M 

Object.included_modules #=> [M, Kernel] 

Вы можете достичь того же с:

class Object 
    include M 
end 

И потому, что все в Ruby, является объектом, вы можете отправить m к каждому объекту , включая экземпляры и классы и модули (например, M):

123.m  #=> "hello" 
'foo'.m  #=> "hello" 
String.m  #=> "hello" 
Object.m  #=> "hello" 
Enumerable.m #=> "hello" 
M.m   #=> "hello" 

объект в смысле is_a? Object

+1

За исключением, конечно: 'BasicObject.new.m # NoMethodError'. –

+0

@ JörgWMittag - это экземпляр BasicObject, фактически являющийся объектом? – Stefan

+0

У этого есть переменные экземпляра, у него есть одноэлементный класс, у него есть класс, вы можете вызывать методы на нем, вы можете сохранить его в переменной, вы можете передать его в качестве аргумента, вы можете вернуть его из метода, есть нет разницы между экземпляром «BasicObject», экземпляром «Object» или экземпляром «String», за исключением того, где указывает его внутренний указатель класса. Итак, да, это определенно ** объект **, но не «объект». Внутри всех реализаций Ruby нет специального представления для экземпляра 'BasicObject', это просто объект, как любой другой, который имеет класс, который просто ... –

0

Еще более странный пример:

▶ module M ; end 
▶ def m ; puts '¡Hola!' ; end 
#⇒ :m 
▶ M.m 
#⇒ ¡Hola! 

Итак, давайте копаться в наследство объекта. Контекст выполнения: main. main, по-видимому, является «специальным» экземпляром Object, распространяя все методы, определенные на нем, чтобы быть видимым повсюду. Поскольку Module экземпляр (M) на самом деле является экземпляром Object, он внезапно реагирует на каждый метод Object. Но у нас просто есть Object, расширенный с помощью метода m.

Примечание: module M ; def m ; end ; end; include M и def m ; end на верхнем уровне делать почти то же самое: как продлить Object с m методом (последний делает этот метод private на Object, хотя.)

Надеется, что это помогает.

+0

Они не делают то же самое. Один добавляет 'm' в' Object', другой смешивает 'M' в' Object'. Это две совершенно разные вещи. В частности, 'def m' создаст' m' метод 'private' экземпляра' Object', и, таким образом, 'M.m' будет' поднимать' 'NoMethoError':' ruby ​​-e 'module M; конец; def m; конец; M.m '# -e: 1: in'

': private method' m ', вызываемый для M: Module (NoMethodError) ' –

+0

@ JörgWMittag Спасибо, что указали, что методы, определенные на' main' становятся 'private'. Этот забавный факт по-прежнему не создает микширования модулей и определения методов на объектах разных вещей. _Изменение модуля, содержащего единственный метод для объекта, ни в коем случае не отличается от объявления этого метода на объекте непосредственно (с точки зрения этого объекта, конечно.) 'Main' weirdness по-прежнему является« основным ». – mudasobwa

+0

Цепочка наследования, таким образом, путь поиска метода, таким образом, 'super' отличается, например. Модуль может быть смешан с несколькими классами (например, «BasicObject»). –

1

"default definee" (то есть модуль, который определяет методы, определенные с def и include d миксинами в верхнем), на верхнем уровне - Object.

Это означает, что M получает включены в Object, т.е. M становится суперкласс Object, вставленный под Kernel. Так как M является экземпляром модуля, а Module является подклассом Object и Object теперь является подклассом M, можно позвонить M.m.

Предок цепь Module является:

[Module, Object, M, Kernel, BasicObject] 

эрго, M находится в методе поиска пути для M, и, следовательно, M.m находит метод, определенный в M.

Смежные вопросы