Hatena::ブログ(Diary)

このブログは証明できない。

2010-04-12

[]自作クラスのオブジェクトハッシュキーにするときの小技。

自作クラスのオブジェクトハッシュキーにするときの小技。というタイトル記事を書いてみました。


自作クラスを定義します。

class Person
  def initialize(name, age)
    @name = name
    @age = age
  end

  attr_accessor :name, :age
end

このクラスのオブジェクトを2つ作ります。それをハッシュキーとして使います。

aoi1 = Person.new("宮崎あおい", 24)
aoi2 = Person.new("宮崎あおい", 24)

hash = {}
hash[aoi1] = 1
hash[aoi2] = 2

puts hash[aoi1] #=> 1
puts hash[aoi2] #=> 2

そうすると、違うキーとして扱われます。インスタンス変数が同じなので、同じキーとして扱って欲しい。長い人生の中には、そんな時もあるでしょう。


ポイントは、Object#eql?メソッドにあります。

puts aoi1.eql? aoi2 #=> false
puts aoi1.equal? aoi2 #=> false

equal?がfalseなのは、オブジェクトが違うので当たり前です。ですが、eql?もfalseになっています。それは、お前が悪いのです。eql?を再定義しなければ、デフォルトでequal?と同じ挙動をするのです。つまり、お前が悪いのです。




eql?メソッドを再定義しましょう。eql?メソッドを再定義する場合は、hashメソッドも再定義する必要があります。

class Person
  def initialize(name, age)
    @name = name
    @age = age
  end

  attr_accessor :name, :age

  def eql?(other)
    @name == other.name && @age == other.age
  end

  def hash
    [@name, @age].hash
  end
end

今度はどうでしょうか。

aoi1 = Person.new("宮崎あおい", 24)
aoi2 = Person.new("宮崎あおい", 24)

puts aoi1.eql? aoi2 #=> true
puts aoi1.equal? aoi2 #=> false

eql?がtrueになっていますね。


さあ、本番です。

aoi1 = Person.new("宮崎あおい", 24)
aoi2 = Person.new("宮崎あおい", 24)

hash = {}
hash[aoi1] = 1
hash[aoi2] = 2

puts hash[aoi1] #=> 2
puts hash[aoi2] #=> 2

できましたよ。宮崎あおい(24)は、唯一無二の存在なのです。

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証