РЕДАКТИРОВАТЬ: Позвольте мне немного рассказать о моих намерениях:
При условии, что объект ruby получает свои методы из методов экземпляра своего класса.
Я пытался «доказать» то, что, добавляя методы экземпляра к классу этого объекта, они затем станут методами для самого объекта.
So:
class Test;end
Test.class.class_eval do
def foo
puts "I am a method in #{self}"
end
end
Test.foo
=> I am a method in Test
Test.class.foo
=> I am a method in Class
Я вообще-то уже разобрался, почему это происходит. Это потому, что Class.class - это ... Класс! Поскольку Class имеет foo как часть своей таблицы методов экземпляра, и поскольку Class.class указывает на себя, он также будет иметь foo как вызываемый метод экземпляра.
Исходный пост следует:
Просто ради того, чтобы больше узнать об объектной модели Ruby, я провел несколько экспериментов, и следующее поведение меня удивило:
Допустим, у нас есть класс Test:
class Test;end
Затем мы class_eval Test.class, чтобы добавить метод к объекту Test:
Test.class.class_eval do
def foo
puts 'foo called!'
end
end
(эквивалентно вызову Test.class.send (: define_method,: foo) ...)
Потом:
irb(main):076:0> Test.foo
=> foo called!
Но отправка foo в класс также работает:
irb(main):006:0> Test.class.foo
=> foo called!
Однако я до сих пор не могу понять, почему. Singleton_class класса не содержит его (единственное возможное объяснение, которое пришло мне в голову, заключалось в том, что каким-то образом метод был добавлен в одноэлементный класс класса):
Test.class.singleton_methods
=> [:nesting, :constants]
Как в этом случае работает поиск метода? Почему отправка: foo в Test.class также вызывает метод? Я что-то упускаю ?
В качестве справки я проделал то же самое с экземпляром Test:
irb(main):001:0> class Test;end
=> nil
irb(main):002:0> _foo = Test.new
=> #<Test:0x007fa2c39e2f38>
irb(main):003:0> _foo.class.class_eval do
irb(main):004:1* def foo
irb(main):005:2> puts 'foo called!'
irb(main):006:2> end
irb(main):007:1> end
=> :foo
irb(main):008:0> _foo.foo
foo called!
=> nil
irb(main):009:0> _foo.class.foo
NoMethodError: undefined method `foo' for Test:Class
Это сработало так, как я ожидал.
Заранее спасибо!