Вопрос

Мне интересно, как можно заставить это работать:

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

Мне бы хотелось, чтобы при добавлении чего-либо в переменную me объект использовал переопределенный метод.

Если я попытаюсь выполнить это, я получу syntax error, unexpected ':', expecting kEND на :<<.

Это было полезно?

Решение

:old<< выглядит как " :old << " ;. Попробуйте просто :"old<<", или, если хотите, <=> (но получайте удовольствие, называя это через это имя).

Другие советы

В символьных литералах допускаются только определенные символы. Вы ищете:

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

Как уже объясняли другие, проблема в том, что old<< не является допустимым идентификатором Ruby. С помощью хитростей вы можете создать метод с таким именем, но вы не можете вызывать его обычными способами, и он, безусловно, не будет распознаваться как оператор.

Тем не менее, все ответы, хотя они наверняка ответили на ваш вопрос, полностью проигнорировали проблему , лежащую в основе : у этого метода вообще не должно быть имени! И если у него нет имени, то проблема его незаконности просто не возникает.

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

В этом случае метод никогда не получает имя, что означает не только то, что нам не нужно придумывать имя для него, но и то, что он не загрязняет пространство имен.

Проблема в :old<<. Он интерпретируется как :old <<, то есть символ :old, за которым следует оператор <<, поэтому это синтаксическая ошибка. Может быть, вы можете попробовать :"old<<"?

Хотя я согласен с thenduks и ephemient, вы можете использовать псевдоним оператора таким образом, а затем использовать send для его вызова, вы также можете использовать наследование классов. например:.

me = "is a string"

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

me << " bob"
puts me #=> is a string appended bob
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top