class Object
def eigenclass
class << self; self; end
end
end
def find_method(klass, name)
m = klass.methods.grep(/^#{name}/)
if m.empty?
puts "Could not find #{name}"
else
puts "Found #{name}: " + m.join(", ")
end
end
class Pela; end
p = Pela.new
# adicionando um método específico apenas para essa instância
def p.bye
puts "BYE!"
end
p.bye
find_method(p.eigenclass, "bye")
puts
# adicionando um método para a classe Pela (método estático)
def Pela.hi
puts "HI!"
end
Pela.hi
find_method(p.eigenclass, "hi")
Output:
c:\rubycode>ruby crazyeigen.rb
BYE!
Could not find bye
HI!
Found hi: hi
Pra onde foi o danado do método bye, ou seja, em que classe ele está definido?
Pensando aqui acho que o que eu quero é impossível em Ruby.
Apesar de internamente em Ruby classes armazenarem métodos, uma classe só vai te dar o nome do método se o método for um método de classe. Por isso que quando temos uma metaclasse, ela pode nos mostrar o nome dos métodos de classe.
Agora quando temos métodos específicos de uma instância, apesar deles estarem internamente armazenados na classe (eigenclass ou singleton class), a classe não tem como lhe fornecer essa informação, apenas a instância através do método methods.
É interessante notar que cada instância tem sua própria eigenclass, que pode ser modificado on-the-fly para adicionar métodos específicos da instância.
A classe de dois Objects são iguais (Object) mas as suas eigenclasses são diferentes, conforme o código abaixo mostra.
class Object
def eigenclass
class << self; self; end
end
end
def find_method(klass, name)
m = klass.methods.grep(/^#{name}/)
if m.empty?
puts "Could not find #{name}"
else
puts "Found #{name}: " + m.join(", ")
end
end
class Pela; end
p = Pela.new
# adding a instance method
def p.bye
puts "BYE!"
end
p.bye
find_method(p.eigenclass, "bye")
find_method(p, "bye")
puts
# check if they are the same...
p1 = Pela.new
p2 = Pela.new
def p1.bye
puts "BYE!!!"
end
puts p1.class, p2.class, p1.class == p2.class
puts p1.eigenclass, p2.eigenclass, p1.eigenclass == p2.eigenclass
find_method(p1, "bye")
find_method(p2, "bye")
puts
find_method(p1.eigenclass, "bye")
find_method(p2.eigenclass, "bye")
Output:
c:\rubycode>ruby crazyeigen.rb
BYE!
Could not find bye
Found bye: bye
Pela
Pela
true
#<Class:#><Pela:0x2b81670>>
#<Class:#><Pela:0x2b811c0>>
false
Found bye: bye
Could not find bye
Could not find bye
Could not find bye