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