2010-07-22 41 views
1

我有一個測試類和一個盒類,在測試類中,我有一個名爲boxHolder的var,它是一個數組,我想覆蓋該數組的方法<。在單身人士內部,我如何訪問moski_call?在Ruby中的覆蓋實例變量數組的操作符和範圍

 
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
+0

按照慣例,rubyists不使用camelCase;它是'box_holder',而不是'boxHolder'等... – 2010-07-22 16:02:08

回答

0

這樣的:

# 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) 
} 
+0

我得到以下錯誤:「'<<':未定義的局部變量或方法'moski_call'爲[]:Array(NameError)」 – 2010-07-22 13:01:10

+0

啊,這個工程,非常感謝...你能解釋爲什麼這個工程,定義moski_call_output解決了問題,但是moski_call和moski_call_output有什麼區別? – 2010-07-22 13:03:40

+0

@moski,'moski_call'是一種方法,'moski_call_output'是一個局部變量。在一個'define_method'塊中,在方法被定義的對象中查找方法 - 在這種情況下是'@ boxholder'。然而@boxholder沒有這樣的方法,所以會出錯。另一方面,局部變量被'define_method'塊(閉包)捕獲,並且可以被訪問。 – horseyguy 2010-07-22 13:15:27

0

什麼:

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

這將宣佈爲實例boxHolder的方法。但boxHolder沒有訪問方法moski_call

+0

它似乎語法不正確,我得到「語法錯誤,意外'。',期待'\ n'或';'」 – 2010-07-22 12:55:49

0

你需要保持獲得「父」 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。