Как получить доступ к родительским классам-призракам в ruby? - PullRequest
2 голосов
/ 10 сентября 2009

Я смотрел первый экранный ролик метапрограммирования от Prag Dave. В какой-то момент он сказал, что ruby ​​вводит «классы-призраки», когда вы добавляете метод в переменную экземпляра. я.

animal = "cat"
def animal.speak
  puts "hola"
end
animal.speak       # => hola
animal.class       # => String

dog = "dog"

dog.speak          # Undefined method `speak' for "dog":String
String.send :speak # NoMethodError: undefined method `speak' for String:Class
animal.send :speak # hola

Где на самом деле магазин методов разговора? Если это невидимый прокси-класс, как мы можем получить доступ к этому прокси-классу?

Ответы [ 2 ]

4 голосов
/ 10 сентября 2009

Метод speak хранится в метаклассе (также известном как собственный класс), который вы называете «классом невидимого прокси». В Ruby переменные экземпляра не имеют места для хранения методов. Они могут хранить только переменные экземпляра и их класс. Поэтому, когда вы добавляете метод к экземпляру, метакласс создается и вставляется в его цепочку классов. Для лучшего понимания внутренних органов я рекомендую эту статью от Klank Boom Klang.

Чтобы попасть в мета-класс, вы можете сделать следующее:

animal = "cat"
def animal.speak
  puts "hola"
end
animal.speak       # => hola
animal.class       # => String

metaclass = class << animal; self; end

metaclass.inspect                        # => #<Class:#<String:0x2c9c460>>
metaclass.instance_methods.index 'speak' # => 102
metaclass.class                          # => Class
1 голос
/ 11 сентября 2009

Некоторые люди называют это "Класс Singleton"

singleton_class = class << animal; self; end

И на самом деле этот одноэлементный класс является хостом для методов класса в любом классе, проверьте этот пример, сначала определив класс Foo с помощью методов класса 'hi' и 'bye':

class Foo
  def self.hi ; p "hi" ; end
  def self.bye ; p "bye" ; end
end
Foo.singleton_methods #=> ["hi","bye"]

Теперь давайте определим метод, который возвращает нам класс синглтона:

class Object
  def singleton_class 
     class << self
       self
     end
  end
end

Теперь попробуйте это:

Foo.singleton_methods #=> ["bye", "hi"]
Foo.singleton_class.instance_methods(false) #=> ["bye", "hi"]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...