Переопределение операторов массива переменных экземпляра в Ruby - PullRequest
3 голосов
/ 01 ноября 2009

Извините за плохое название, я не знаю, как это назвать.

У меня есть что-то вроде этого в Ruby:

class Test
  def initialize
    @my_array = []
  end
  attr_accessor :my_array
end
test = Test.new
test.my_array << "Hello, World!"

Для переменной экземпляра @my_array я хочу переопределить оператор <<, чтобы я мог сначала обработать все, что в него вставлено. Я попробовал @my_array.<<(value) как метод в классе, но он не сработал.

Ответы [ 6 ]

10 голосов
/ 01 ноября 2009

Я думаю, вы ищете это:

class Test
  def initialize
    @myarray = []
    class << @myarray
      def <<(val)
        puts "adding #{val}" # or whatever it is you want to do first
        super(val)
      end
    end
  end
  attr_accessor :myarray
end

Хорошая статья об этой и смежных темах на Понимание классов Ruby Singleton .

2 голосов
/ 01 ноября 2009

Я не уверен, что на самом деле это то, что вы можете сделать напрямую.

Вы можете попробовать создать производный класс из Array, реализуя ваши функциональные возможности, например:

class MyCustomArray < Array
  def initialize &process_append
    @process_append = &process_append
  end
  def << value
    raise MyCustomArrayError unless @process_append.call value
    super.<< value
  end
end

class Test
  def initialize
    @my_array = MyCustomArray.new
  end
  attr_accessor :my_array
end
1 голос
/ 01 ноября 2009

Вот, пожалуйста ...

$ cat ra1.rb

class Aa < Array
  def << a
    puts 'I HAVE THE CONTROL!!'
    super a
  end
end

class Test
  def initialize
    @my_array = Aa.new
  end
  attr_accessor :my_array
end

test = Test.new
test.my_array << "Hello, World!"
puts test.my_array.inspect
$ ruby ra1.rb
I HAVE THE CONTROL!!
["Hello, World!"]
$ 
0 голосов
/ 25 августа 2010

Я расширяю класс, создавая метод, который обеспечивает доступ к переменной экземпляра.

        class KeywordBid
          def override_ignore_price(ignore_price)
            @ignorePrice = ignore_price
          end
        end
0 голосов
/ 01 ноября 2009

Вы можете расширить метакласс любого отдельного объекта, не создавая совершенно новый класс:

>> i = []
=> []
>> class << i
>>   def <<(obj)
>>     puts "Adding "+obj.to_s
>>     super
>>   end
>> end
=> nil
>> i << "foo"
Adding foo
=> ["foo"]
0 голосов
/ 01 ноября 2009
a = []
a.instance_eval("alias old_add <<; def << value; puts value; old_add(value); end")

Очень хакерский, и у меня в голове ...

Просто поменяйте "ставит значение" с любой предварительной обработкой, которую вы хотите сделать.

...