7

この質問に答える試みで:どうすれば集合の違いを大文字と小文字を区別しないようにすることができますか?、大文字と小文字を区別しない文字列のセットを作成しようとして、セットと文字列を試していました。しかし、何らかの理由でStringクラスを再度開くと、セットに文字列を追加したときにカスタムメソッドが呼び出されません。以下のコードでは出力が表示されませんが、オーバーロードした演算子の少なくとも1つが呼び出されることを期待していました。どうしてこれなの?

編集:ハッシュメソッドなどを定義するString2などのカスタムクラスを作成した場合、オブジェクトをセットに追加すると、これらのメソッドが呼び出されます。なぜ文字列ではないのですか?

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'
4

1 に答える 1

4

のソースコードを見ると、Setストレージに単純なハッシュを使用しています。

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

Stringしたがって、開く代わりに行う必要があることは開いているように見えますSet。私はこれをテストしていませんが、それはあなたに正しい考えを与えるはずです:

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
于 2012-12-21T18:34:45.187 に答える