ruby – Overriding =〜方法对String子类产生不一致

我覆盖了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上重现这些结果.有人知道为什么会发生这种情况吗?是bug吗

解决方法

String#=~方法的源代码中,Ruby处理特殊情况,其中参数是由解析器使用的内置Regexp类型,这是我们编写s =〜/ abc /的情况.

rb_reg_match方法可以作为Regexp#=~方法.

因此,如果你真的想要这个行为,你可以通过猴子修补Regexp类来接受MyString对象的操作,但这可能很容易出错.

另一种方法是组合.您可以包括Forwardable模块,也可以使用普通的old_方法.以下是一个例子:

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"

相关文章

以下代码导致我的问题: class Foo def initialize(n=0) @n = n end attr_accessor :n d...
这是我的spec文件,当为上下文添加测试“而不是可单独更新用户余额”时,我得到以下错误. require 's...
我有一个拦截器:DevelopmentMailInterceptor和一个启动拦截器的inititializer setup_mail.rb. 但我想将...
例如,如果我有YAML文件 en: questions: new: 'New Question' other: recent: ...
我听说在RSpec中避免它,let,let !,指定,之前和主题是最佳做法. 关于让,让!之前,如果不使用这些,我该如...
我在Rails中使用MongoDB和mongo_mapper gem,项目足够大.有什么办法可以将数据从Mongoid迁移到 Postgres...