Rubyで==メソッドを実装して2つのオブジェクトを比較する方法
Rubyでは、2つのオブジェクトが「同じ」であるかどうかを判断するために、オブジェクトやその値を比較します。この記事では、==メソッドの仕組みと、自分のクラスに同等性を実装してオブジェクト比較を強化する方法を解説します。
まず基本となるのが次のような比較です。
1 == 1 # true
この書き方はご存じの方も多いでしょう。しかし、==が単なる構文ではなくメソッドであることを知っていますか?
ここが重要なポイントです。==はメソッドなので、自分のクラスに実装することで、クラスをより強力にできます。本記事ではその方法を学びましょう。
2つのオブジェクトが「同じ」であるとは?
文字列は次のように比較できます。
"foo" == "foo"
単語と文字が同じであれば等しいとみなされ、この式はtrueを返します。
これが機能するのは、Stringクラスが==メソッドを実装しており、文字列同士を正しく比較できるようになっているからです。
では、もしStringクラスが==を実装していなかったらどうなるのでしょうか?その場合、RubyはObjectクラスの==実装を使用します。デフォルトでは、これはオブジェクトの中身ではなくオブジェクトの同一性(object id)をテストします。
例:
Object.new == Object.new # false String.new == String.new # true
Objectがfalseを返すのは、新しく生成された2つのオブジェクトは異なるオブジェクトIDを持つためです。一方、Stringは内容ベースで比較するため、2つの新しい空文字列は同じ内容(空)となり、trueが返ります。
同等性の実装方法
それでは、ここまで学んだことを活かして、独自クラスを比較可能にしてみましょう。==メソッドを定義すれば、自分のクラスのインスタンス同士が「等しい」とみなされる条件を正確に定義できます。
例:
class Product
attr_reader :name, :price
def initialize(name, price)
@name, @price = name, price
end
def ==(other)
self.name == other.name &&
self.price == other.price
end
end
p1 = Product.new('book', 49)
p2 = Product.new('book', 49)
p1 == p2 # true
この==メソッドでは、名前と価格の両方が一致した場合のみ、2つのProductオブジェクトは等しいとみなされます。
注意点:
このメソッドを実装しない場合(あるいはComparableモジュールを利用しない場合)、オブジェクトは値ではなくオブジェクトIDで比較されてしまいます。
また補足として、Structを使用する場合は==がすでに実装されているため、自分で定義する必要はありません。
===(トリプルイコール)については?
==がメソッドなら、===もメソッドなのかと疑問に思うかもしれません。答えはYesです。
では、両者の違いは何でしょうか?
JavaScriptでは明確な違いがあります。==は型が異なる場合に暗黙の型変換を試み(例:1と'1')、===は「厳密な」等価性のチェックに使われます。
しかし、Rubyにはそのような区別はありません。===の意味は、それを実装しているクラスによって変わります。
多くの場合、===は単なる==のエイリアスです。たとえばStringやObjectがそうです。
以下は、===に特別な意味を持たせている主な組み込みクラスの一覧です。
| クラス | 意味 |
|---|---|
| Range | objが範囲内の要素であればtrue、そうでなければfalseを返す。 |
| Regexp | 文字列に対して正規表現マッチを行う。 |
| Module | objがmodのインスタンス、またはmodの子孫クラスのインスタンスであればtrueを返す。 |
| Proc | objを引数としてブロックを呼び出す(Proc#callと同様)。これにより、procオブジェクトがcase文のwhen句の対象として使えるようになる。 |
まとめ
この記事では、==メソッドを実装することで独自クラスをより強力にする方法と、==と===の違いについて学びました。同等性を適切に実装することで、オブジェクトを値ベースで自然に比較できるようになり、コードの可読性と保守性も向上します。
最後まで読んでいただきありがとうございました。この記事が役に立ったら、ぜひ周りの人にもシェアしてください🙂
-
iPhone / iOS(Swift)で2つのNSDateを比較する方法を解説
Swiftで2つのNSDateを比較する方法この記事では、Swiftを使って2つのNSDate(日付)を比較する方法を解説します。日付の比較は、予約アプリやスケジュール管理など、実際のiOSアプリ開発でもよく使われる処理です。今回はシミュレーターではなく、Playgroundを使って動作を確認していきます。1. 比較用の日付を2つ作成するまず、NSDateComponentsを使って2つの異なる日付を作成しましょう。ここでは「1993年6月5日」と「1995年2月4日」という2つの日付を定義します。let dateOne = NSDateComponents() dateOne.day = 5
-
Rubyのfreezeメソッド完全解説 – オブジェクトの可変性と不変性を理解しよう
オブジェクトが「変更可能(ミュータブル)」であるとは、どういう意味なのでしょうか? 難しい言葉に構える必要はありません。「可変性(ミュータビリティ)」とは、単純に「オブジェクトの内部状態を後から変更できる」という意味です。これはすべてのオブジェクトのデフォルトの挙動であり、freeze(凍結)されたオブジェクトや、言語側で特別扱いされている一部のオブジェクトだけが例外となります。 つまり、Rubyのすべてのオブジェクトが変更可能というわけではないのです。 なぜ数値やシンボルは変更できないのか? たとえば、整数・シンボル、さらにはtrueやfalse(これらもすべてオブジェクトです)が変化するの