シンプルなミックスイン
CoddyのLuaジャーニー「オブジェクト指向プログラミング」セクションの一部 — レッスン 51/70。
コンポジションを使うと、オブジェクトを他のオブジェクトの中に入れることができます。しかし、無関係なクラス間で振る舞いを共有したい場合はどうすればよいでしょうか?
Player と MenuItem の両方に :describe() メソッドが必要になるかもしれませんが、それらは親クラスを共有していません。そこで、ミックスインの出番です。
ミキシンは単に関数を含むテーブルです。これらの関数をクラスにコピーすることで、クラスに「ミックス」します。
local Printable = {}
function Printable:describe()
print("Object: " .. tostring(self))
end
function Printable:log(message)
print("[LOG] " .. message)
endこのミックスインをクラスに適用するには、ミックスインテーブルからクラステーブルに各関数をコピーします:
local function applyMixin(class, mixin)
for key, value in pairs(mixin) do
class[key] = value
end
end
local Player = {}
Player.__index = Player
applyMixin(Player, Printable) -- これで Player は :describe() と :log() を持つようになりますミックスインを適用した後、任意の Player インスタンスは、あたかもクラスに直接定義されているかのように、これらのメソッドを呼び出すことができます:
local p = setmetatable({}, Player)
p:log("Player created") -- [LOG] プレイヤーが作成されました継承とは異なり、ミックスインは親子関係を作成しません。単に一つのテーブルから別のテーブルへ関数をコピーしているだけです。
これにより、ミックスインは、ロギング、シリアル化、記述メソッドなどのユーティリティ動作を、他に共通点のないクラス間で共有するのに最適です。
チャレンジ
簡単ミックスインを使用してタグ付けシステムを構築しましょう!任意のクラスに適用できる Taggable ミックスインを作成し、オブジェクトにタグのコレクションを管理する機能を提供します。これは、アイテム、投稿、またはラベルが必要なあらゆるエンティティを分類するのに役立ちます。
コードは3つのファイルに分けて構成します:
Taggable.lua: 2つのメソッドを含むミックスインテーブルを作成します::addTag(tag)—self.tagsにタグを追加します(テーブルが存在することを前提とします):listTags()— すべてのタグをTags: tag1, tag2, tag3の形式で出力します(空の場合はTags: none)
Article.lua: タイトルを保存し、空のtagsテーブルを初期化するコンストラクタ:new(title)を持つ Article クラスを作成します。Taggable ミックスインを適用して、Article インスタンスにタグ付け機能を持たせます。記事のタイトルを返す:getTitle()メソッドを含めてください。main.lua: ここにapplyMixinヘルパー関数を記述します(Article.lua で require を介して使用します)。次に、記事のタイトルと2つのタグの入力を読み取ります。Article を作成し、両方のタグを追加し、タイトルを出力して、すべてのタグをリスト表示します。
3つの入力を受け取ります:
- 記事のタイトル(文字列)
- 追加する1つ目のタグ(文字列)
- 追加する2つ目のタグ(文字列)
出力には、記事のタイトルに続いてそのタグを表示する必要があります:
Title: {title}
Tags: {tag1}, {tag2}例えば、入力が Lua Basics、programming、tutorial の場合、出力は以下のようになります:
Title: Lua Basics
Tags: programming, tutorial注意:ミックスインメソッドが機能するのは、Article インスタンスがミックスインメソッドの操作対象となる tags テーブルを持っているからです。ミックスインはこのテーブルを作成しません。Article コンストラクタが作成します。ミックスインは共有される振る舞いを提供するだけです!
自分で試してみよう
-- タギングシステムのメインファイル
local Taggable = require('Taggable')
local Article = require('Article')
-- TODO: applyMixin 関数を実装する
-- この関数は、mixin テーブルからターゲットテーブルへすべてのメソッドをコピーする必要があります
function applyMixin(target, mixin)
-- TODO: mixin をループで回し、各メソッドを target にコピーする
end
-- 入力を読み込む
local title = io.read()
local tag1 = io.read()
local tag2 = io.read()
-- TODO: 指定された title で Article を作成する
-- TODO: 両方のタグを article に追加する
-- TODO: Title: {title} という形式でタイトルを表示する
-- TODO: listTags メソッドを使用してすべてのタグをリスト表示する
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。