2012-05-18 55 views
0

這是我想做什麼:有沒有辦法將方法傳遞給同一對象的方法?

class Directory 
    def doSomething 
    end 

    def subs 
    # => an array of Directory objects 
    end 

    def recursively (method) 
    self.subs.each do |sub| 
     sub.method 
     sub.recursively method 
    end 
    end 
end 

cd = Directory.new 

cd.recursively 'doSomething' 
# ...and extra points if theres a way to: 
cd.recursively.doSomething 

要地理解這一點我創建一個小腳本,將更改目錄中的文件以及它的所有子目錄。這些子目錄只會擴展Directory對象。

那麼有沒有辦法將方法作爲另一種方法的參數傳遞?

回答

1

你可以使用Object#send,其中method是一個字符串或符號表示的方法名稱,如您的第一個例子。只要改變你的#recursively這樣:

def recursively(method) 
    subs.each do |sub| 
    sub.send method 
    sub.recursively method 
    end 
end 

UPDATE

爲了您的「加分」的問題,並在MEGAS的回答撿了,這裏是在一個基於枚舉的方法刺傷。放棄這一到你的目錄:

def recursively 
    Enumerator.new do |y| 
    subs.each do |sub| 
     y.yield sub 
     sub.recursively.each do |e| 
     y.yield e 
     end 
    end 
    end 
end 

,並調用它是這樣的:

cd.recursively.each { |d| d.doSomething } 
0

看看這個讓你在正確的方向前進:

module Recursion 
    def recursively(&block) 
    output = block.call(self) 
    output.recursively(&block) unless output.nil? 
    end 
end 

class Number 
    include Recursion 

    def initialize(value) 
    @value = value 
    end 

    def next 
    @value > 0 ? Number.new(@value - 1) : nil 
    end 

    def print 
    puts @value 
    self.next 
    end 
end 

Number.new(10).recursively(&:print) 
1

是的,你可以做到這一點 -

class Directory 
    def doSomething 
    end 

    def subs 
     # => an array of Directory objects 
    end 

    def recursively (method) 
     self.subs.each do |sub| 
      sub.method.call 
      sub.recursively method 
     end 
    end 
end 

dir = Directory.new 
ds = dir.method :doSomething 

dir.recursively ds 
1

我覺得這裏的應該從可枚舉專業化each方法模塊。當您實施each方法時,Enumerable模塊將提供許多方便的方法,如map, drop等。

class Directory 
    include Enumerable 

    def initialize 
    # here you should build @objects - a whole list of all objects in 
    # the current direcory and its subdirectories. 
    @objects = .... 
    end 

    def each   
    if block_given? 
     @objects.each { |e| yield(e) } 
    else 
     Enumerator.new(self, :each) 
    end 
    end 

    ... 
end 

然後你可以遍歷在優雅的方式,所有對象:

@directory = Directory.new('start_directory') 

@directory.each do |object| 
    puts object.size # this will prints the sizes for all objects in directory 
    object.do_some_job # this will call method on object for all your objects 
end 

這人會給大小的數組中的所有對象在目錄

@directory.map { |object| object.size } #=> [435435,64545,23434,45645, ...] 

aditional的例子:

例如,您需要獲取包含所有對象的索引和大小的列表

@directory.each_with_index.map { |object, index| [index, object.size] } 

#=> [ [0,43543], [1,33534], [2,34543564], [3,345435], ...] 
+0

我想說我真的很喜歡這條路線到目前爲止的語義。 'block_given?'檢查的是什麼? – webdesserts

+1

它檢查你是否通過了一個區塊,查看更新 – megas

+0

我認爲這對我的項目將是一個巨大的幫助,我感謝你的努力。我確實認爲,儘管答案@羅布戴維斯提供了更好的答案最初的問題。所以我會檢查他的未來訪客。如果我能讓你更多,我會。 – webdesserts

相關問題