108 votes

Comment utiliser define_method pour créer des méthodes de classe ?

Ceci est utile si vous essayez de créer des méthodes de classe de manière métaprogrammatique :

def self.create_methods(method_name)
    # To create instance methods:
    define_method method_name do
      ...
    end

    # To create class methods that refer to the args on create_methods:
    ???
end

Ma réponse à suivre...

194voto

fguillen Points 11849

Je pense que dans Ruby 1.9 vous pouvez le faire :

class A
  define_singleton_method :loudly do |message|
    puts message.upcase
  end
end

A.loudly "my message"

# >> MY MESSAGE

25voto

Vincent Robert Points 16530

Je préfère utiliser send pour appeler define_method, et j'aime aussi créer une méthode de métaclasse pour accéder à la métaclasse :

class Object
  def metaclass
    class << self
      self
    end
  end
end

class MyClass
  # Defines MyClass.my_method
  self.metaclass.send(:define_method, :my_method) do
    ...
  end
end

10voto

Joseph Jaber Points 2922

C'est la méthode la plus simple en Ruby 1.8+ :

class A
  class << self
    def method_name
      ...
    end
  end
end

8voto

Chinasaur Points 910

Dérivé de : Jay y Pourquoi qui proposent également des moyens de rendre le tout plus joli.

self.create_class_method(method_name)
  (class << self; self; end).instance_eval do
    define_method method_name do
      ...
    end
  end
end

Mise à jour Il s'agit d'une méthode plus concise (tant que vous ne définissez qu'une seule méthode de cette manière) qui reste autonome :

self.create_class_method(method_name)
  (class << self; self; end).send(:define_method, method_name) do
    ...
  end
end

mais notez que l'utilisation de send() pour accéder à des méthodes privées comme define_method() n'est pas nécessairement une bonne idée (d'après ce que j'ai compris, cette fonction disparaîtra dans Ruby 1.9).

8voto

Artur Beljajev Points 11

À utiliser dans Rails si vous voulez définir les méthodes d'une classe de manière dynamique à partir de la préoccupation :

module Concerns::Testable
  extend ActiveSupport::Concern

  included do 
    singleton_class.instance_eval do
      define_method(:test) do
        puts 'test'
      end
    end
  end
end

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X