L’introspection consiste à obtenir des informations sur un objet au moment de l’exécution d’un programme. Voyons à quoi ça ressemble.

Créons une classe Inspector qui va extraire certaines informations des objets qu’on lui donnera:

class Inspector
  class << self
    def classname(o)
      o.class.name
    end

    def methods(c)
      c.instance_methods(false)
    end

    def parameters(o, m)
      o.method(m).parameters
    end
  end
end

Dans cet exemple nous allons récupérer le nom de la classe, le nom des méthodes et certaines informations sur les arguments des méthodes.

Voyons comment ça marche en récupérant le nom de la classe Object:

>> load './introspection.rb'
>> p Inspector.classname(Object.new)
"Object"

Maintenant ajoutons une classe C avec quelques méthodes:

class Inspector
  class << self
    def classname(o)
      o.class.name
    end

    def methods(c)
      c.instance_methods(false)
    end

    def parameters(o, m)
      o.method(m).parameters
    end
  end
end

class C
  def foo
  end

  def bar(arg1, arg2)
  end

  def baz(arg1, *args, &block)
  end
end

Les méthodes de la classe C ne font rien. C’est normal, ce qui nous intéresse ici c’est leur signature. D’abord le nom de la classe:

>> load './introspection.rb'
>> p Inspector.classname(C.new)
"C"

Facile. Maintenant récupérons les méthodes:

>> p Inspector.methods(C)
[:foo, :bar, :baz]

Pas mal. Encore plus fort, inspectons les arguments de chacune des méthodes:

>> Inspector.methods(C).each do |m|
?>   p Inspector.parameters(C.new, m)
>> end
[]
[[:req, :arg1], [:req, :arg2]]
[[:req, :arg1], [:rest, :args], [:block, :block]]

Voilà, c’était une rapide mise en bouche du comment faire ?. Pour le à quoi ça sert ?, il faudra attendre un prochain article ;)

À demain.