2014-09-20 33 views
0

我想使用委託將映射從字符串傳遞到字符,然後再返回到字符串結果。Ruby:在委託方法上執行附加命令

require 'forwardable' 

module Map 
    module String 
    extend Forwardable 

    def self.included(base) 
     base.send :extend, Forwardable 
    end 

    # Map for String 
    delegate map: :chars 
    end 
end 

class String 
    include Map::String 
end 

由於這是原來我想執行字符串加入委派法履行職責之後。如何修改委託行以包含其他更改?我在網上看到的最接近的東西是SimpleDelegator__setobj__。但是這沒有很好的記錄,我無法確定如何使用它。

我嚴格關於委託或SimpleDelegate的

我在尋找的等效行爲尋找一個答案是這樣的:

module Map 
    module String 

    def map(*args, &block) 
     if (!args.compact.empty? || !block.nil?) 
     self.chars.map(*args,&block).join 
     else 
     self.chars.map(*args,&block) 
     end 
    end 
    end 
end 

class String 
    include Map::String 
end 

我期待了解如何與委託做到這一點。

回答

1

Fowardable docs很搞笑 - 就好像第一個例子沒有一百個錯誤就會運行一樣。你的僞代碼告訴ruby轉發方法調用String#map,這不存在,String#chars,你想加入()的結果呢?跳過所有的方法調用,只寫puts "some_string"。所以你的問題似乎沒有多大意義。無論如何,Forwardable#delegate()不允許您將一個名稱映射到另一個名稱。

至於SimpleDelegat ** **或者,你可以這樣做:

module Map 
    require 'delegate' 

    class MyStringDecorator < SimpleDelegator 
    def map 
     chars.shuffle.join('|') 
    end 
    end 
end 


d = Map::MyStringDecorator.new 'hello' 
puts d.map 

--output:-- 
h|o|l|l|e 

響應編輯:等效行爲我正在尋找..

的問題是紅寶石不會讓你這樣做:

class String < SomeClass 
end 

這就是include做,你需要能夠做到這一點,才能使用delega將所有發送給一個類的方法調用轉發給另一個類。這是你能做的最好的:

require 'delegate' 

class MyString < DelegateClass(String) 
    def map(*args, &block) 
    if (!args.compact.empty? || !block.nil?) 
     self.chars.map(*args,&block).join 
    else 
     self.chars.map(*args,&block) 
    end 
    end 
end 

s = MyString.new 'hello' 
puts s.upcase 
puts s.map {|letter| letter.succ } 

--output:-- 
HELLO 
ifmmp 

或者:

require 'forwardable' 

class MyString 
    extend Forwardable 

    def initialize(str) 
    @str = str 
    end 

    def_delegators :@str, :upcase, :capitalize, :[], :chars #etc., etc., etc. 
    #Or: delegate({[:upcase, :capitalize, :[], :chars] => :@str}) 
    #Or: instance_delegate({[:upcase, :capitalize, :[], :chars] => :@str}) 


    def map(*args, &block) 
    if (!args.compact.empty? || !block.nil?) 
     self.chars.map(*args,&block).join 
    else 
     self.chars.map(*args,&block) 
    end 
    end 
end 

s = MyString.new('hello') 
puts s.upcase 
puts s.map {|letter| letter.succ } 

--output:-- 
HELLO 
ifmmp 

當然,你總是可以覆蓋String#method_missing()做你想做什麼。你讀到關於讓你認爲它可以取代的代表是什麼?

+0

我試圖在委託之後完成這種聯接方法的原因是因爲我的初始代碼很好,但返回一個數組。所以我認爲委託應該內置一些功能來處理轉發後要處理的數據。至於method_missing,我已經試過將它轉發到字符,並最終打破紅寶石。看到這裏的代碼:http://stackoverflow.com/questions/25837679/why-does-ruby-hang-when-i-use-method-missing-on-string-to-redirect-to-chars。當數組包含字符串時,基本上變平變成無限循環。並呼籲要求呼籲變平。 – 2014-09-23 19:17:33