Pregunta

Estoy interesado en cómo se podría lograr que esto funcione:

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

Me gustaría que cuando algo se agregue a la variable me, el objeto utilizará el método redefinido.

Si intento ejecutar esto, obtengo syntax error, unexpected ':', expecting kEND en :<<.

¿Fue útil?

Solución

:old<< parece " :old << " ;. Pruebe simplemente :"old<<", o si realmente quiere, <=> (pero diviértase llamándolo con ese nombre).

Otros consejos

Solo se permiten ciertos caracteres en literales de símbolos. Estás buscando:

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

Como otros ya han explicado, el problema es simplemente que old<< no es un identificador legal de Ruby. Puede, con trucos, crear un método con ese nombre, pero no puede llamarlo de la manera normal, y ciertamente no será reconocido como un operador.

Sin embargo, todas las respuestas hasta ahora, aunque ciertamente han respondido a su pregunta, han ignorado por completo el problema subyacente : ¡ese método ni siquiera debería tener un nombre en primer lugar! Y si no tiene un nombre, entonces el problema de que el nombre sea ilegal simplemente ni siquiera surge.

#!/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

En este caso, el método nunca se nombra, lo que no solo significa que no tenemos que inventar un nombre para él, sino que también contamina el espacio de nombres.

El problema es con :old<<. Se interpreta como :old <<, es decir, un símbolo :old seguido del operador <<, por lo que es un error de sintaxis. Quizás puedas probar :"old<<"?

Si bien estoy de acuerdo con thenduks y ephemient, puede alias al operador de esa manera y luego usar send para llamarlo, pero también puede usar herencia de clase. por ejemplo:

me = "is a string"

class << me
  def <<(text)
    super
    puts "appended #{text}"
  end
end

me << " bob"
puts me #=> is a string appended bob
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top