Как получить доступ к родительским классам-призракам в ruby?

StackOverflow https://stackoverflow.com/questions/1405743

  •  05-07-2019
  •  | 
  •  

Вопрос

Я смотрел первый скринкаст по метапрограммированию ruby от прага Дейва.В какой-то момент он сказал, что ruby вводит "классы-призраки", когда вы добавляете метод к переменной экземпляра.i.

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

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

Это было полезно?

Решение

Способ speak хранится в метаклассе (также известном как собственный класс), который вы называете "невидимым прокси-классом".В Ruby переменным экземпляра негде хранить методы.Они могут хранить только переменные экземпляра и их класс.Таким образом, когда вы добавляете метод к экземпляру, создается метакласс и вставляется в его цепочку классов.Для лучшего понимания внутренних компонентов я рекомендую эта статья из Кланк-Бум-Кланга.

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

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

Другие советы

Некоторые ppl называют это "Одноэлементным классом".

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"]
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top