hakeの日記

Windows環境でプログラミングの勉強をしています。

オブジェクトの比較

Rubyの勉強

自分で定義したクラスのオブジェクト同士の比較を行いたい場合はComparableをインクルードして、演算子<=>を定義する。演算子<=>はクラス内の要素の何を比較するかの定義。これによってobja == objb 等の比較の記述ができる。
Enumerableをインクルードしてeachメソッドを定義することで、上記のComparableをインクルードを行ったクラスのオブジェクト集合に対して#sort、#collect、#max他の処理が行えるようになる。
下記の例ではMIMEタイプを保持するクラスMimeと、Mimeクラスのオブジェクトの集合を扱うMimeListを定義している。

class Mime
  include Comparable   # <=>を定義する必要あり
  attr_reader :string, :main, :sub

  def initialize(str = "")
    if str =~ /\//
      @string = str.strip
      @main , @sub = @string.split(/\//)
    else
      @string, @main, @sub = "", "", ""
    end
  end
  
  # 何について比較を行うかの定義
  # ここでは@mainと@subのStringの文字コード比較
  # もし@mainが同じであれば@subで比較を行う
  def <=>(other)
    ret = @main <=> other.main
    return ret if ret != 0
    @sub <=> other.sub
  end
end

class MimeList
  include Enumerable  # eachを定義する必要あり
                      # 対象クラスには<=>が定義されている必要あり
  attr_reader :list
  
  def initialize
    @list = Array.new
  end
  
  # Mimeオブジェクトをリストに追加
  def add(mime)
    @list.push(mime)
  end
  
  def each
    @list.each{|mime| yield mime}
  end
end


w = Mime.new("application/excel")
x = Mime.new("application/excel")
y = Mime.new("text/html")
z = Mime.new("application/x-tar")

p w == x # => ture
p w  > x # => false
p w  > y # => false
p z  > w # => true

mimelist = MimeList.new
mimelist.add(w)
mimelist.add(x)
mimelist.add(y)
mimelist.add(z)


# リスト中のMimeオブジェクトをアルファベット順にソート
sorted =  mimelist.sort
sorted.each{|mime| puts "#{mime.string}"}
  # => application/excel
  # => application/excel
  # => application/x-tar
  # => text/html

# 逆順でソート
sorted =  mimelist.sort{|a,b| b <=> a}
sorted.each{|mime| puts "#{mime.string}"}
  # => text/html
  # => application/x-tar
  # => application/excel
  # => application/excel

p mimelist.max.string # => text/html