Рубиновый собственный класс (класс сиглета) создан? Для которого?
Запутался в метапрограммировании Ruby.
Итак, из урока я узнал следующее:
cat = "kitty"
cat.upcase # "KITTY"
cat.poop # undefined 'poop'
def cat.poop
puts 'pooooooo...'
end
cat.upcase # "KITTY"
cat.poop # "pooooooo..."
Таким образом, это означает, что метод poop уже предназначен для объекта cat, который имеет класс String. Из известного учебника "Программирование на Ruby", определяя cat.poop, на самом деле происходит то, что Ruby создает анонимный класс, он же singleton или eigenclass, который теперь является классом объекта cat, тогда исходный класс String становится суперклассом недавно созданный собственный класс.
Тогда это смутило меня. Смотрите следующий код:
cat.poop # "pooooooo...", it works, for sure
cat.class # "String" | but this is NOT some other class
cat = "kate"
cat.poop # poop not defined
3 вопроса:
не похоже, что когда-либо создавался новый класс при определении метода poop. Или, может быть, он был создан, но метод "#class" автоматически перенаправил вызов суперкласса "#class"? Что правильно? Как мы проверяем?
если мы определим другой метод, скажем, cat.run, то будет создан другой собственный класс или нет? Какова будет иерархия классов тогда?
если cat переопределено как "kate", корма не найдена. Зачем? Разве корма не должна быть доступна для кошки?
Спасибо!
1 ответ
- смотреть на
cat.singleton_class
а такжеcat.singleton_methods
, - Определите пару одноэлементных методов на
cat
а затем посмотрите наcat.singleton_class.instance_methods
и вы увидите их обоих там. Вы можете получить подсказку об иерархии сcat.singleton_class.ancestors
, - Вы определили
cat
быть каким-то совершенно новым объектом сейчас. Почему у него такие же методы? Если вы говоритеcat = "string"
тогда вы можете позвонитьcat.upcase
, но если вы позже переназначитеcat = 5
, конечно, ты не можешь звонитьcat.upcase
,