Menu
Coddy logo textTech

等価性のチェック

CoddyのLuaジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 17/70。

__tostring がオブジェクトの表示方法を制御することを学びました。もう 1 つの便利なメタメソッドが __eq です。これは == 演算子を使ったときに、2 つのオブジェクトを等しいと見なす条件を定義します。

デフォルトでは、== を使って2つのテーブルを比較すると、それらがメモリ上でまったく同じテーブルかどうかが確認されます。同一のデータを持つ別々のオブジェクトは false を返します:

local user1 = {id = 101, name = "Alice"}
local user2 = {id = 101, name = "Alice"}
print(user1 == user2)  -- 出力: false (異なるテーブル)

__eqを使うと、独自の等価性ロジックを定義できます。クラスでは、__tostringと同じように、クラステーブル内の関数として追加します。等価性を機能させるには、両方のオブジェクトが同じメタテーブルを共有している必要があります。

local User = {}
User.__index = User

function User:new(id, name)
    local instance = {}
    setmetatable(instance, self)
    instance.id = id
    instance.name = name
    return instance
end

function User:__eq(other)
    return self.id == other.id
end

これで、2つの User オブジェクトは、他のフィールドに関係なく、同じ ID を共有していれば equal と見なされます。

local u1 = User:new(101, "Alice")
local u2 = User:new(101, "Bob")
local u3 = User:new(202, "Alice")

print(u1 == u2)  -- 出力: true (同じID)
print(u1 == u3)  -- 出力: false (異なるID)

このパターンは、オブジェクトが一意の識別子を持つ現実世界のエンティティを表す場合に役立ちます。データベースレコード、ゲームエンティティ、またはメモリ上の位置よりもアイデンティティが重要なあらゆるオブジェクトを比較する際に使用できます。

challenge icon

チャレンジ

簡単

Product クラスを作成して、まったく異なるテーブルに保存されている場合でも、2つの製品が同じ Item かどうかを判定できるようにしましょう! 小売システムでは、製品に固有の SKU コード(Stock Keeping Units)が割り当てられていることがよくあります。価格の変更など、その他の詳細にかかわらず、同じ SKU を共有していれば、2つの製品は equal とみなされます。

コードを2つのファイルに整理します。

  • Product.lua: 標準的な prototype pattern を使用して Product class を定義します。各製品には sku(固有の識別子)と name を格納します。2つの製品が same SKU を持つ場合に equal とみなされるよう、__eq metamethod を Implement します。equal 判定では name は関係ありません。
  • main.lua: Product module を Require し、複数の製品 instances を作成します。== operator を使用して comparing し、カスタムの equal ロジックを確認します。

Product class には、次の要素を含めます。

  • :new(sku, name) Constructor
  • :getInfo() method。次の format の string を Return します:[sku]: [name]
  • 製品を SKU で comparing する __eq metamethod

6つの inputs が与えられます。

  1. 最初の製品の SKU
  2. 最初の製品の名前
  3. 2番目の製品の SKU
  4. 2番目の製品の名前
  5. 3番目の製品の SKU
  6. 3番目の製品の名前

main ファイルで、与えられた inputs を使用して3つの製品を作成し、次の内容を print します。

  1. 各製品の info(3行)
  2. product 1 と product 2 を comparing した result
  3. product 1 と product 3 を comparing した result

たとえば、inputs が ABC123Wireless MouseABC123Mouse (Updated)XYZ789Keyboard の場合、Output は次のようになります。

ABC123: Wireless Mouse
ABC123: Mouse (Updated)
XYZ789: Keyboard
true
false

最初の2つの製品は、name が different であるにもかかわらず、same SKU を持つため equal であることに注目してください。これは、実際の在庫システムが name の変更や更新を通じて製品を追跡する方法そのものです。

自分で試してみよう

-- Productモジュールを読み込む
local Product = require('Product')

-- 入力を読み取る
local sku1 = io.read()
local name1 = io.read()
local sku2 = io.read()
local name2 = io.read()
local sku3 = io.read()
local name3 = io.read()

-- TODO: 入力を使って3つのProductインスタンスを作成する

-- TODO: 各製品の情報を出力する(3行)

-- TODO: 製品1と製品2を比較した結果を出力する

-- TODO: 製品1と製品3を比較した結果を出力する
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

オブジェクト指向プログラミングのすべてのレッスン

自分で練習してみよう: Luaオンラインコンパイラ