2016-11-09 64 views
1

有一個簡單的辦法,而不在其外部影響的任何擴展標準庫類像String一個模塊內的功能的功能呢?例如(無效):安全延伸的標準庫類

module Foo 
    class String 
    def hello 
     "hello #{self}!" 
    end 
    end 

    class Bar 
    def greet name 
     name.hello 
    end 
    end 
end 

結果我在尋找:

Foo::Bar.new.greet 'Tom' #=> hello Tom! 
'Tom'.hello #=> NoMethodError 

我知道像期望的功能創建MyString < String的解決方案,但我寧願不叫MyString.new('foo')每我想在模塊中使用一個字符串。

我意識到這可能不被視爲好的做法,我只是希望擴大我對語言的理解。

回答

3

什麼你要找的是Refinement

的設計方案是旨在減少猴子修補對猴子打補丁的班 其他用戶的影響。 加細提供了一種 本地擴展類。

module Foo 
    refine String do 
    def hello 
     "hello #{self}!" 
    end 
    end 
end 

puts 'Tom'.hello 
#=> undefined method `hello' for "Tom":String 
using Foo 
puts 'Tom'.hello 
#=> hello Tom! 

內用Bar類細化:

# Without refinement 
class Bar 
    def greet(name) 
    name.hello 
    end 
end 

puts Bar.new.greet('Tom') 
#=> undefined method `hello' for "Tom":String 

# With refinement 
class Bar 
    using Foo 
    def greet(name) 
    name.hello 
    end 
end 

puts Bar.new.greet('Tom') 
#=> hello Tom! 

有關作用域的完整信息,方法查找和東西看看文檔鏈接我提供了:)

附:請注意,Rubinius開發人員在哲學上反對Refinements,因此不會實施它們(c)JörgW Mittag。

+0

是的,我很確定他想要改進,這不是誤解。 –

+0

也許,提供一小段代碼來說明如何使用精化? –

+0

是的,當然是一個錯字。一個細化'String'類的代碼片段將是最受歡迎的 –