Ruby中==运算符的正确实现与双向比较问题
解决Ruby自定义类与字符串双向==比较的问题
你遇到的问题是自定义类MyClass与字符串比较时,obj == str返回true,但str == obj返回false——这是因为后者调用的是String类的==方法,它会先检查被比较对象是否为String实例,非String实例直接返回false,而你又不想修改String类。
解决方案:实现coerce方法
Ruby的运算符重载机制里,coerce方法用于处理不同类型对象之间的运算/比较,当左侧对象的运算符无法处理右侧类型时,会调用右侧对象的coerce方法,将双方转换为可兼容的类型后再执行操作。
给MyClass添加coerce方法,当和String类型比较时,把自身转换为对应的字符串值,让Ruby可以用String的比较逻辑来处理:
class MyClass attr_accessor :var def initialize(v) @var = v end def to_s @var.to_s end def inspect @var.inspect end def ==(other) self.var == other end # 添加coerce方法 def coerce(other) if other.is_a?(String) [other, self.var] else super end end # ... 其他操作@var的方法 end str = "test" obj = MyClass.new("test") puts obj # 输出"test" p obj # 输出"test" puts obj == str # true puts str == obj # true 现在正常了
原理说明
当执行str == obj时,String的==方法发现obj不是String实例,会调用obj.coerce(str),返回[str, obj.var](也就是["test", "test"]),然后Ruby会执行转换后的比较str == obj.var,自然返回true。
这种方式不需要修改String类,完全在自定义类内部解决问题,符合你的需求。
内容的提问来源于stack exchange,提问作者PKP
相关产品推荐
相关产品推荐

