Menu
Coddy logo textTech

シンプルなミックスイン

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

コンポジションを使うと、オブジェクトをほかのオブジェクトの中に配置できます。しかし、関連のないクラス間で振る舞いを共有したい場合はどうすればよいでしょうか?

PlayerMenuItem はどちらも :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などのユーティリティ動作を、その他の点では共通点のないクラス間で共有するのに最適です。

challenge icon

チャレンジ

簡単

mixin を使ってタグ付けシステムを構築しましょう!任意の class に適用できる Taggable mixin を作成し、オブジェクトがタグのコレクションを管理できるようにします。これは、項目、投稿、またはラベルが必要なあらゆるエンティティの分類に役立ちます。

コードを3つのファイルに分けて整理します。

  • Taggable.lua:2つのメソッドを含む mixin table を作成します。
    • :addTag(tag)self.tags にタグを追加します(table が存在することを前提とします)
    • :listTags():すべてのタグを Tags: tag1, tag2, tag3 の形式で出力します(空の場合は Tags: none
  • Article.lua:タイトルを保存し、空の tags table を初期化する constructor :new(title) を持つ Article class を作成します。Article の instance にタグ付け機能を持たせるため、Taggable mixin を適用します。記事のタイトルを返す :getTitle() method も含めます。
  • main.lua:ここで applyMixin helper function を記述します(require を使って Article.lua で使用します)。次に、記事のタイトルと2つのタグの入力を読み取ります。Article を作成し、両方のタグを追加し、タイトルを出力して、すべてのタグを一覧表示します。

3つの入力を受け取ります。

  1. 記事のタイトル(string)
  2. 追加する最初のタグ(string)
  3. 追加する2番目のタグ(string)

出力には、記事のタイトルに続いてタグが表示されます。

Title: {title}
Tags: {tag1}, {tag2}

たとえば、入力が Lua Basicsprogrammingtutorial の場合、出力は次のようになります。

Title: Lua Basics
Tags: programming, tutorial

Article の 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メソッドを使用してすべてのタグを一覧表示する
quiz icon腕試し

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

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

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