一组字符串和重新打开字符串

7
为了回答这个问题:如何使集合差异对大小写不敏感?,我试图使用集合和字符串进行实验,尝试创建一个不区分大小写的字符串集合。但是出现了一个问题,当我重新打开String类时,当我将一个字符串添加到集合中时,没有调用任何自定义方法。在下面的代码中,我看不到任何输出,但我期望被重载的运算符之一被调用。为什么会这样呢?
编辑:如果我创建一个自定义类,比如String2,在其中定义哈希方法等,当我将对象添加到集合中时,这些方法确实会被调用。为什么String不能这样做?
require 'set'

class String
  alias :compare_orig :<=>
  def <=> v
    p '<=>'
    downcase.compare_orig v.downcase
  end

  alias :eql_orig :eql?
  def eql? v
    p 'eql?'
    eql_orig v
  end

  alias :hash_orig :hash
  def hash
    p 'hash'
    downcase.hash_orig
  end
end

Set.new << 'a'
1个回答

4

查看Set源代码,它使用简单的哈希表进行存储:

def add(o)
  @hash[o] = true
  self
end

看起来你需要做的是打开 Set 而不是打开 String。我没有测试过,但应该能给你正确的想法:

class MySet < Set
  def add(o)
    if o.is_a?(String)
      @hash[o.downcase] = true
    else
      @hash[o] = true
    end
    self
  end
end

编辑

正如评论中所述,这可以以更简单的方式实现:

class MySet < Set
  def add(o)
    super(o.is_a?(String) ? o.downcase : o)
  end
end

1
一个简单的 super(o.is_a?(String) ? o.downcase : o) 可能是更好的选择。 - mu is too short
谢谢。没错,那个可以运行。如果我创建一个自定义类,比如 String2,在其中定义一个哈希方法等,当我将对象添加到集合中时,这些方法确实被调用。为什么?(我编辑了我的问题)。 - akonsu
Ruby源代码(https://github.com/ruby/ruby/blob/trunk/hash.c#L1195)可能会给出一些线索。在MRI中,`String`作为哈希键似乎得到了特殊处理。 - Luke

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接