2014-02-20 62 views
0

對Ruby的安靜新我找不出什麼東西。 下面是一個示例代碼Ruby嘗試以編程方式避免子類中的多重定義

class Big 
    def self.metaclass; class << self; self; end; end 

    def self.convertor b 
    metaclass.instance_eval do 
     define_method(:convert) do |val| 
     return b val 
     end 
    end 
    end 
end 

class Small < Big 
    convertor { |v| v.to_i + 1 } 
end 

puts Small.convert('18') 

目的是有很多子類來大的,我喜歡以避免在每個

def convert(val) 
    return conversion_specific_to_subclass(val) 
end 

定義做前一種方法,我只是爲每個一行子類。但不能讓它工作。 我在做什麼錯了?有沒有更好的方法來實現我所希望的?

在此先感謝

編輯:問這裏是錯誤的代碼產生(紅寶石2.1.0)

test2.rb:4:in `convertor': wrong number of arguments (0 for 1) (ArgumentError) 
from test2.rb:14:in `<class:Small>'` 
+0

你是什麼意思「不起作用」?有錯誤嗎?其他輸出?請更具體一些。 – Linuxios

+0

使用amperstamp(b&)我然後有:test2.rb:14:'':未定義的方法'轉換器'爲Small:Class(NoMethodError)希望它會幫助;) – zedryas

回答

3

你太過於複雜 - 因爲你只需要將塊綁定到特定的方法名就可以了!

class Big 
    def self.converter(&block) 
    define_singleton_method :convert, &block 
    end 
end 

class Small < Big 
    converter {|v| v.to_i + 1 } 
end 

這樣一來,當你調用Small::converter,這將定義爲接受在塊ARGS定義的參數列表中的類方法,並且返回值將是你的塊的返回值。

+0

沒想到,+1。 – Linuxios

+0

非常感謝 - 確實更簡單 – zedryas

+0

OUPS - 沒有完全理解 - 調用Small.convert時我們調用生成的函數時怎麼辦? – zedryas

0

試試這個代碼:

class Big 
    def self.metaclass; class << self; self; end; end 

    def self.convertor(&b) 
    metaclass.instance_eval do 
     define_method(:convert) do |val| 
     return b[val] 
     end 
    end 
    end 
end 

class Small < Big 
    convertor { |v| v.to_i + 1 } 
end 

puts Small.convert('18') 

有兩個你的代碼存在問題。一,你必須使用&參數捕獲塊。所以,這是新的方法聲明:

def self.convertor(&b) 

最後,你有你的回用塊調用語法來調用該塊,像這樣:

return b[val] 

或者這樣:

return b.call(val) 

您不能調用類似b val的塊。

另外,在Ruby中始終在括號中包含括號是很好的風格。

+0

這已經完成了,非常感謝:) :)。快速的問題是最好是使用塊,或在Big#convertor方法中使用yield?最後,我如何關閉這個主題? – zedryas

+0

@dryas:你可以使用yield,但是Chris的解決方案比較乾淨。另外,通過接受答案,您可以將問題標記爲已解決。 – Linuxios

相關問題