Les opérateurs Ruby peuvent-ils être aliasés?
-
05-07-2019 - |
Question
Ce qui m'intéresse, c'est de savoir comment cela fonctionnerait:
me = "this is a string"
class << me
alias :old<< :<<
def <<(text)
old<<(text)
puts "appended #{text}"
end
end
J'aimerais que lorsque quelque chose soit ajouté à la variable me
, l'objet utilise la méthode redéfinie.
Si j'essaie de l'exécuter, je reçois syntax error, unexpected ':', expecting kEND
à :<<
.
La solution
:old<<
ressemble à & "; :old
<<
&". Essayez simplement :"old<<"
, ou si vous le souhaitez vraiment, <=> (mais amusez-vous à l'appeler par ce nom).
Autres conseils
Seuls certains caractères sont autorisés dans les littéraux de symboles. Vous recherchez:
alias :"old<<" :"<<"
Comme d'autres l'ont déjà expliqué, le problème est simplement que old<<
n'est pas un identifiant Ruby légal. Vous pouvez, avec des astuces, créer une méthode portant ce nom, mais vous ne pouvez pas l'appeler de manière habituelle, et elle ne sera certainement pas reconnue en tant qu'opérateur.
Cependant, jusqu’à présent, toutes les réponses, bien qu’ils aient certainement répondu à votre question, ont complètement ignoré le problème sous-jacent : cette méthode ne devrait même pas avoir de nom! Et s'il n'a pas de nom, le problème de son illégalité ne se pose tout simplement pas.
#!/usr/bin/env ruby
require 'test/unit'
require 'stringio'
class TestOperatorDecorator < Test::Unit::TestCase
def setup; @old_stdout, $> = $>, (@fake_stdout = StringIO.new) end
def teardown; $> = @old_stdout end
def test_that_me_dot_append_writes_to_stdio
me = 'this is a string'
class << me
old_method = instance_method :<<
define_method :<< do |text|
old_method.bind(self).(text)
puts "appended #{text}"
end
end
me << 'Test'
assert_equal "appended Test\n", @fake_stdout.string
end
end
Dans ce cas, la méthode n'est jamais nommée, ce qui signifie non seulement que nous n'avons pas à inventer de nom, mais également qu'elle ne pollue pas l'espace de nom.
Le problème vient de :old<<
. Il est interprété comme :old <<
, c’est-à-dire un symbole :old
suivi de l’opérateur <<
. Il s’agit donc d’une erreur de syntaxe. Peut-être que vous pouvez essayer :"old<<"
?
Bien que je sois d’accord avec thenduks et ephemient, vous pouvez aliaser l’opérateur de cette façon puis utiliser send pour l’appeler, mais vous pouvez également utiliser l’héritage de classe. par exemple:
me = "is a string"
class << me
def <<(text)
super
puts "appended #{text}"
end
end
me << " bob"
puts me #=> is a string appended bob