2009-10-22 8 views
1

Je suis intéressé par la façon dont on pourrait aller à obtenir que cela fonctionne:Les opérateurs Ruby peuvent-ils être aliasés?

me = "this is a string" 
class << me 
    alias :old<< :<< 
    def <<(text) 
    old<<(text) 
    puts "appended #{text}" 
    end 
end 

Je voudrais que quand quelque chose est ajouté à la variable me, l'objet utilisera la méthode redéfinie.

Si j'essaye de courir ceci, j'obtiens syntax error, unexpected ':', expecting kEND à :<<.

+0

OP semble triste: << – Nakilon

Répondre

3

:old<< ressemble à ":old<<". Essayez juste :old, ou si vous voulez vraiment, :"old<<" (mais amusez-vous en l'appelant par ce nom).

+0

Supposons que je veuille vraiment l'appeler ': old <<'. Est-ce que la seule façon de l'appeler sera d'envoyer? – Geo

+1

Je pense que c'est idiot - pourquoi ne pas choisir un vrai nom? - mais oui, 'send (:" old << ", texte)' fonctionnera. En passant, je ne peux pas penser à d'autres méthodes pour appeler quelque chose avec un nom étrange comme ça. – ephemient

+0

Juste par curiosité :) – Geo

1

Le problème est avec :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<<"?

7

Seuls certains caractères sont autorisés dans les littéraux de symbole. Vous recherchez:

alias :"old<<" :"<<" 
2

Comme d'autres l'ont déjà expliqué, le problème est simplement que old<< n'est pas un identifiant légal Ruby. Vous pouvez, avec des astuces, créer une méthode avec ce nom, mais vous ne pouvez pas l'appeler de la manière habituelle, et elle ne sera certainement pas reconnue comme un opérateur.

Cependant, toutes les réponses jusqu'à présent, alors qu'ils ont certainement répondu à votre question, ont complètement ignoré le problème sous-jacente: cette méthode ne devrait même pas avoir un nom en premier lieu! Et s'il n'a pas de nom, alors le problème de l'illégalité du nom ne se pose même 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 ne fait jamais nommé, ce qui signifie non seulement que nous ne devons pas inventer un nom pour cela, cela signifie aussi qu'il ne pollue pas l'espace de noms.

0

Bien que je sois d'accord avec thenduks et ephemient, vous pouvez alias l'opérateur de cette façon, puis utiliser send pour l'appeler, 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