Рубиновый собственный класс (класс сиглета) создан? Для которого?

Запутался в метапрограммировании 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 вопроса:

  1. не похоже, что когда-либо создавался новый класс при определении метода poop. Или, может быть, он был создан, но метод "#class" автоматически перенаправил вызов суперкласса "#class"? Что правильно? Как мы проверяем?

  2. если мы определим другой метод, скажем, cat.run, то будет создан другой собственный класс или нет? Какова будет иерархия классов тогда?

  3. если cat переопределено как "kate", корма не найдена. Зачем? Разве корма не должна быть доступна для кошки?

Спасибо!

1 ответ

Решение
  1. смотреть на cat.singleton_class а также cat.singleton_methods,
  2. Определите пару одноэлементных методов на cat а затем посмотрите на cat.singleton_class.instance_methods и вы увидите их обоих там. Вы можете получить подсказку об иерархии с cat.singleton_class.ancestors,
  3. Вы определили cat быть каким-то совершенно новым объектом сейчас. Почему у него такие же методы? Если вы говорите cat = "string" тогда вы можете позвонить cat.upcase, но если вы позже переназначите cat = 5, конечно, ты не можешь звонить cat.upcase,
Другие вопросы по тегам