Pergunta

Eu estava assistindo o primeiro screencast rubi metaprogramming por prag dave. Em algum momento ele disse que ruby ??introduzir 'classes fantasmas' quando você adicionar um método para uma variável de instância. 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

Onde é realmente a loja método de falar? Se é uma classe de proxy invisível, Como podemos ter acesso a essa classe de proxy?

Foi útil?

Solução

O speak método é armazenado em um metaclasse (também conhecido como um eigenclass), o que você chama uma "classe de proxy invisível". Em Ruby, variáveis ??de instância não têm lugar para armazenar métodos. Eles só podem armazenar variáveis ??de instância e sua classe. Então, quando você adicionar um método para uma instância, uma metaclasse é criado e inserido na sua cadeia de classe. Para uma melhor compreensão dos internos, eu recomendo este artigo de Klank lança Klang.

A fim de obter a classe meta, você pode fazer o seguinte:

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

Outras dicas

Alguns ppl chamá-lo de "Singleton Classe"

singleton_class = class << animal; self; end

E, na verdade, essa classe singleton é o anfitrião para métodos de classe em qualquer classe, verifique este exemplo, primeiro através da definição de classe Foo com métodos de classe 'oi' e 'tchau':

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

Agora vamos definir um método que retorna a classe singleton para nós:

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

Agora, tente o seguinte:

Foo.singleton_methods #=> ["bye", "hi"]
Foo.singleton_class.instance_methods(false) #=> ["bye", "hi"]
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top