Bezdepbonusu7Программирование: статьи и ответы

Вопрос

Переопределение операторов массива переменных экземпляра в Ruby и определение области видимости

Автор вопроса: Moski DoskiОтветов: 3

У меня есть тестовый класс и класс коробки, в тестовом классе у меня есть переменная с именем boxHolder, которая представляет собой массив, я хочу переопределить метод ‹* для этого массива. Как я могу получить доступ к moski_call внутри синглтона?

class Test
  attr_accessor :boxHolder

  def initialize()
   super
   self.boxHolder = Array.new

   class << @boxHolder
     def <<(box)
       box.setPositionWithinColumn(moski_call)
       super(box)
     end
   end
  end

  def moski_call
    "YAAAAAAAAAAAAAAAAAAAA"
  end
end

class Box
  def initialize
  end

  def setPositionWithinColumn(str)
    puts "got a string #{str}"
  end
end

# test
box = Box.new
test = Test.new
test.boxHolder 
  • По соглашению рубисты не используют camelCase; это box_holder, а не boxHolder и т. д ... Marc-André Lafortune 22.07.2010

rubyarrayssingleton

Ответы

Ответ 1 · horseyguy

нравится:

# need this or else `moski_call` method is looked up in context of @boxholder
moski_call_output = moski_call

class << @boxholder; self; end.send(:define_method, :<<) { |box|
     box.setPositionWithinColumn(moski_call_output)
     super(box)
}

Ответ 2 · Edu

Как насчет:

def self.boxHolder.<< (box)
   box.setPositionWithinColumn(moski_call)
   super(box)
end

Это объявит метод для вашего экземпляра boxHolder. Но boxHolder не имеет доступа к методу moski_call

Ответ 3 · Marc-André Lafortune

Вам необходимо сохранить доступ к "родительскому" объекту Test. Это можно сделать, используя тот факт, что блоки являются замыканиями:

parent = self # to be accessible in the closure

@boxHolder.define_singleton_method(:<<) do |box|
  box.setPositionWithinColumn(parent.moski_call)
  super(box)
end

Примечание: define_singleton_method является новым в Ruby 1.9, поэтому либо обновите, require 'backports/1.9.1/kernel/define_singleton_method', либо сделайте class << @boxHolder; define_method(:<<){ "..." } end при использовании более старого Ruby.

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы