Tout d'abord, une petite pointe de style:
self.class.send(:define_method, :say_hello, lambda { test })
Vous pouvez le rendre un peu plus agréable en utilisant le nouveau proc littérale de Ruby 1.9:
self.class.send(:define_method, :say_hello, -> { test })
Mais vous n'en avez pas besoin. Ruby a quelque chose qui s'appelle des blocs, qui sont fondamentalement un morceau de code que vous pouvez passer en argument à une méthode. En fait, vous avez déjà utilisé des blocs, depuis lambda
est juste une méthode qui prend un bloc en argument et renvoie un Proc
. Toutefois, define_method
déjà prend un bloc de toute façon, il n'est pas nécessaire de passer d'un bloc à l' lambda
qui la convertit en Proc
qu'il transmet à la define_method
qui reconvertit en un bloc:
self.class.send(:define_method, :say_hello) { test }
Comme vous l'avez déjà remarqué, vous êtes à la définition de la méthode sur la mauvaise classe. Vous définissez sur l' Example
classe, depuis l'intérieur d'une méthode d'instance comme initialize
, self
est l'objet courant (c'est à dire ex1
ou ex2
dans @mikej exemple), ce qui signifie qu' self.class
est ex1
's de la classe, qui est - Example
. Donc, vous l'écrasez la même méthode, encore et encore.
Ceci conduit à considérer un comportement non désiré:
ex1 = Example.new('ex1')
ex2 = Example.new('ex2') # warning: method redefined; discarding old say_hello
ex1.say_hello # => ex2 # Huh?!?
Au lieu de cela, si vous voulez un singleton méthode, vous devez définir dans la classe singleton:
(class << self; self end).send(:define_method, :say_hello) { test }
Cela fonctionne comme prévu:
ex1 = Example.new('ex1')
ex2 = Example.new('ex2')
ex1.say_hello # => ex1
ex2.say_hello # => ex2
En Ruby 1.9, il y a une méthode qui fait que:
define_singleton_method(:say_hello) { test }
Maintenant, cela fonctionne de la façon dont vous le souhaitez, mais il y a un niveau plus élevé problème ici: ce n'est pas du code Ruby. Il est Ruby syntaxe, mais ce n'est pas du code Ruby, c'est Régime.
Maintenant, est un brillant de la langue et de l'écriture Régime de code dans la syntaxe Ruby est certainement pas une mauvaise chose à faire. Il bat l'enfer hors de l'écriture, du Java ou du code PHP dans la syntaxe Ruby, ou, comme ce fut le cas dans un StackOverflow question hier, Fortran-57 du code de syntaxe Ruby. Mais ce n'est pas aussi bonne que l'écriture de Ruby code dans la syntaxe Ruby.
Scheme est un langage fonctionnel. Les langages fonctionnels utilisation des fonctions (plus précisément, les fermetures de fonction) pour l'encapsulation et de l'état. Mais Ruby n'est pas un langage fonctionnel, c'est un langage orienté objet et les langages à objets utiliser des objets pour l'encapsulation et de l'état.
Ainsi, la fonction de fermetures de devenir des objets et capturé variables deviennent des variables d'instance.
Nous pouvons également venir à ce à partir d'un angle complètement différent: ce que vous faites, c'est que vous êtes à la définition d'un singleton méthode, qui est une méthode dont le but est de définir un comportement qui est spécifique à un objet. Mais la définition que singleton méthode pour chaque instance de la classe, et de la définition de la même singleton méthode pour chaque instance de la classe. Nous avons déjà un mécanisme pour définir le comportement de chaque instance d'une classe: les méthodes d'instance.
Deux de ces arguments proviennent des directions complètement opposées, mais ils arrivent à la même destination:
class Example
def initialize(test='hey')
@test = test
end
def say_hello
@test
end
end