Existe-t-il un alias_method pour une méthode de classe?


10

Considérez la classe suivante:

class Foo
  def an_inst_method
    'instance method'
  end

  def self.a_class_method
    'class method'
  end

  alias_method :a_new_inst_method, :an_inst_method
end

Ce n'est pas un problème et vous pouvez appeler Foo.new.a_new_inst_methodsans problème.

J'aimerais pouvoir avoir une méthode de classe comme Foo.add_widget(*items)et l'alias pour que je puisse faire quelque chose comme:

Foo.add_widget 'item1'
Foo.add_widgets 'item2', 'item3'

Donc, essentiellement, il a un "style rubis" 1.minuteet 2.minutesje veux donc alias un Foo.add_widgetappel qui Foo.add_widgetsappelle exactement la même méthode. Je sais que je pourrais l'envelopper, mais je pense que je devrais pouvoir le faire de manière plus propre.

Considérez ma tentative d'essayer quelque chose comme ceci:

class Foo
  def an_inst_method
    'instance method'
  end

  def self.a_class_method
    'class method'
  end

  alias_method :a_new_inst_method, :an_inst_method
  alias_method :a_new_class_method, :a_class_method
end

Cependant, j'obtiens l'erreur suivante:

NameError (undefined method `a_class_method' for class `Foo')

Il semble donc que cela ne fonctionne pas pour les méthodes de classe. Comment dois-je procéder?


Réponses:


9

alias_methodalias une méthode d'instances du récepteur. Les méthodes de classe sont en fait des méthodes d'instance définies sur la classe singleton d'une classe.

class MyClass
  def self.a
    "Hello World!"
  end
end

method_1 = MyClass.method(:a).unbind
method_2 = MyClass.singleton_class.instance_method(:a)

method_1 == method_2
#=> true

Pour alias une méthode d'instance définie sur la classe singleton, vous pouvez soit l'ouvrir à l'aide de la class << objectsyntaxe.

class << MyClass
  alias_method :b, :a
end

MyClass.b
#=> "Hello World!"

Ou vous pouvez vous y référer directement en utilisant la singleton_classméthode.

MyClass.singleton_class.alias_method :c, :a

MyClass.c
#=> "Hello World!"

Si vous êtes toujours dans le contexte de la classe self, vous vous référerez à la classe. Ainsi, ce qui précède pourrait également s'écrire:

class MyClass
  class << self
    def a
      "Hello World!"
    end
    alias_method :b, :a
  end
end

Ou

class MyClass
  def self.a
    "Hello World!"
  end
  singleton_class.alias_method :c, :a
end

Ou une combinaison des deux.


5

Vous pouvez encapsuler les méthodes de classe et leurs alias_methodappels dans un module séparé et incorporer ce module dans votre classe via extend:

class Foo
  def an_inst_method
    'instance method'
  end
  alias_method :a_new_inst_method, :an_inst_method

  module ClassMethods
    def a_class_method
      'class method'
    end
    alias_method :a_new_class_method, :a_class_method
  end

  extend ClassMethods
end

Hey! J'ai oublié la extend ClassMethodssolution. +1
aarona

4

La chose importante à comprendre est qu'il n'existe pas de méthode de classe dans Ruby.

Une méthode de classe n'est vraiment qu'une méthode singleton. Il n'y a rien de spécial dans les méthodes de classe. Chaque objet peut avoir des méthodes singleton. Nous les appelons simplement «méthodes de classe» lorsque l'objet est un Classcar «la méthode singleton d'une instance de Class» est trop longue et trop lourde.

Attendre! Ai-je dit "méthode singleton"?

Une autre chose importante à comprendre est qu'il n'existe pas de méthode singleton en Ruby.

Une méthode singleton n'est en fait qu'une ancienne méthode d'instance ennuyeuse ordinaire de la classe singleton. Les méthodes singleton n'ont rien de spécial. Ce ne sont que des méthodes d'instance comme toute autre méthode d'instance.

En fait, Ruby n'a que des méthodes d'instance. Aucune fonction, aucun constructeur, aucune méthode statique, aucune méthode de classe, aucune fonction de module, aucune méthode singleton.

La question n'est pas "est-ce une méthode de classe, est-ce une méthode singleton", mais plutôt "dans quel module cette méthode est-elle définie?"

Les "méthodes singleton" sont en fait des méthodes d'instance définies dans la classe singleton. La syntaxe pour accéder à la classe singleton de fooest

class << foo
end

Il existe également une méthode Object#singleton_classqui renvoie la classe singleton d'un objet.

Pourquoi suis-je si agressif sur le fait que chaque méthode est une méthode d'instance et que les méthodes de classe n'existent pas? Parce que cela signifie que le modèle objet de Ruby est beaucoup plus simple que les gens ne le pensent! Après tout, dans votre question, vous montrez déjà que vous savez comment alias les méthodes d'instance, mais vous dites que vous ne savez pas comment alias les méthodes de classe. Mais c'est faux! Vous ne savez comment les méthodes de classe d'alias, parce qu'ils ne sont que des méthodes d'instance . Si vous aviez appris ce fait correctement, vous n'auriez jamais eu besoin de poser cette question!

Une fois que vous comprenez que chaque méthode est une méthode d'instance et que ce que nous appelons les "méthodes singleton" ne sont que des méthodes d'instance de la classe singleton, la solution devient claire:

singleton_class.alias_method :a_new_class_method, :a_class_method

Remarque: lorsque j'ai écrit ci-dessus «il n'y a rien de tel que X», je voulais dire «qu'il n'y a pas de chose telle que X dans le langage Ruby ». Cela ne signifie pas que ces concepts n'existent pas dans la communauté Ruby .

Nous parlons régulièrement de «méthodes singleton» et de «méthodes de classe», simplement parce que c'est plus facile que de parler de «méthodes d'instance de la classe singleton» ou de «méthodes d'instance de la classe singleton d'un objet qui se trouve être une instance de la Classclasse ". Il existe des méthodes comme même Object#define_singleton_method, Object#singleton_method, Object#singleton_methods, Module#private_class_method, Module#public_class_method, et Module#module_functiondans la bibliothèque de base Ruby. Mais il est toujours important de se rappeler que ce ne sont pas des concepts de langage. Ce sont des concepts communautaires qui n'existent que dans nos têtes et dans les noms de certaines méthodes de bibliothèque.


2

OK, on ​​dirait que je peux faire quelque chose comme ça et ça marchera:

class Foo
  def an_inst_method
    'instance method'
  end

  def self.a_class_method
    'class method'
  end

  alias_method :a_new_inst_method, :an_inst_method

  class << self
    alias_method :a_new_class_method, :a_class_method
  end
end

Foo.a_class_method # => "class method" 
Foo.a_new_class_method # => "class method"

Si quelqu'un a des informations utiles sur le langage Ruby ici et souhaite soumettre une réponse complète, je vous donnerai un +1.


1
Lorsque vous ne class << selfsuiviez par alias_method :a_new_class_method, :a_class_methodvous appelez en fait alias_methodsur la classe singleton Foo. Une autre façon d'écrire ceci est: singleton_class.alias_method :a_new_class_method, :a_class_methoddans le contexte de la classe.
3limin4t0r

Que voulez-vous de plus d'une réponse? Je veux dire, c'est probablement la solution la plus propre.
Dave Newton

@ 3limin4t0r si vous en faites une réponse, je vais la +1. Merci pour ces informations supplémentaires.
aarona

@DaveNewton vous avez raison mais parce que j'ai aussi une philosophie selon laquelle si quelqu'un peut fournir des informations plus significatives à un problème même s'il résout indirectement le problème, je pense que cela devrait également être récompensé.
aarona

2

alias_methodfonctionne sur l'instance, vous devez donc aller plus loin et opérer sur l' Classinstance ou la métaclasse de la classe . Ruby a un modèle d'objet sauvage qui peut être une sorte de rupture cérébrale, mais il vous donne également une tonne de puissance:

class Foo
  def an_inst_method
    'instance method'
  end

  alias_method :a_new_inst_method, :an_inst_method

  class << self
    def a_class_method
      'class method'
    end

    alias_method :a_new_class_method, :a_class_method
  end
end

Je travaille avec ruby ​​dans un contexte de rails depuis environ une décennie, mais ce n'est que récemment que j'ai commencé à plonger profondément dans le modèle objet. Il y a tellement de trucs sympas disponibles!
aarona
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.