2014-02-28 32 views
10

我推翻的=~方法的String一個子類:重寫=〜上的字符串子類方法產生不一致

class MyString < String 
    def =~(obj) 
    "Overridden method." 
    end 
end 
s = MyString.new "abc" 

的重寫的方法正確地稱爲在某些情況下:

r = /abc/ 
s =~ r    # => "Overridden method." 
s.send(:=~, r)  # => "Overridden method." 
s.send(:=~, /abc/) # => "Overridden method." 

而在別人被繞過,而String#=~被稱爲:

s =~ /abc/   # => 0 
s =~ (/abc/)  # => 0 

我可以在Ruby 1.8.7,2.1.0上重現這些結果。有人知道爲什麼發生這種情況?這是一個錯誤嗎?

+0

我不知道這是否可以幫助,但關於Ruby 1.9.3和2.0,明確發送'=〜'工作:'s.send 「=〜」/ ABC /'# >「覆蓋方法。」。 –

+0

對我來說看起來像一個bug。我認爲問題出現在MRI中的[parse.y](https://github.com/ruby/ruby/blob/trunk/parse.y#L2229)上。如果右手操作是正則表達式,它將調用不同的路徑。 –

+0

出於某種原因,這也適用:'s =〜(/ abc /)',但要求該課程的用戶將括號內的「Regexp」括起來將是一件麻煩事。 – Gabriel

回答

1

在源爲String#=~方法,紅寶石處理特殊情況,其中參數是內置由解析器,它是這種情況時,我們寫s =~ /abc/使用Regexp類型的。

可以發現rb_reg_match方法是Regexp#=~方法。因此,如果你真的想要這種行爲,你可以猴子修補Regexp類來接受=〜運算符的MyString的對象,但這可能非常容易出錯。

另一種方法是組合。您可以包含Forwardable模塊或使用普通舊版method_missing。這裏有一個例子:

class MyString 
    attr_reader :string 

    def initialize(str) 
    @string = str 
    end 

    def method_missing(*args) 
    string.public_send(*args) 
    end 

    def =~(obj) 
    "Overriden" 
    end 
end 

s = MyString.new "abc" 
s =~ /abc/    # => "Overriden" 
s =~ Regexp.new("abc") # => "Overriden" 
相關問題