Menu
Coddy logo textTech

親メソッドの呼び出し

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

メソッドを完全にオーバーライドしたいとは限らない場合があります。代わりに、extendsしてparentのbehaviorを拡張したいことがあります。つまり、parentが行うことを実行してから、さらに何かを追加するということです。これを実現するには、childのオーバーライド内からparentのmethodを直接呼び出します。

このテクニックでは、parentクラス名とともにドット構文を使用し、最初の引数としてselfを明示的に渡します:

local Animal = {}
Animal.__index = Animal

function Animal:new(name)
    local obj = {name = name}
    setmetatable(obj, Animal)
    return obj
end

function Animal:speak()
    print(self.name .. " makes a sound")
end

-- Dog は親の振る舞いを拡張する
local Dog = {}
Dog.__index = Dog
setmetatable(Dog, {__index = Animal})

function Dog:new(name)
    local obj = Animal.new(Animal, name)
    setmetatable(obj, Dog)
    return obj
end

function Dog:speak()
    Animal.speak(self)  -- 親のメソッドを先に呼び出す
    print(self.name .. " wags tail happily")
end

重要な行は Animal.speak(self) です。親クラスに対してドット構文を使い、self を手動で渡すことで、独自の動作を追加する前に元のメソッドを呼び出します。

local buddy = Dog:new("Buddy")
buddy:speak()
-- 出力:
-- Buddy が音を出す
-- Buddy が嬉しそうにしっぽを振る

このパターンは、重複したくない重要な処理を親のメソッドが行う場合に便利です。子は、親のロジックを最初に、最後に、あるいは自身のコードの途中で実行することもでき、behavior の組み合わせ方を完全に制御できます。

challenge icon

チャレンジ

簡単

通常の Personbehavior を拡張する FormalPerson を使って、greeting system を構築しましょう!person が自分自身を紹介する方法を完全に置き換えるのではなく、formal version はまず標準の introduction を行い、その後に丁寧なひと言を追加します。

コードは次の3つのファイルに分けて構成します。

  • Person.lua: person の名前を保存する :new(name) constructor を持つ Base class です。person の名前に続けて says hi を prints する :introduce() method も含めます。これは拡張される Base behavior です。
  • FormalPerson.lua: Person から継承する Child class です。その Constructor では、名前を処理するために parent の Constructor を Call します。:introduce() method を Override しますが、parent の behavior を完全に置き換えるのではなく、まず parent の method を Call するために Person.introduce(self) を使用し、その後、person の名前に続けて bows politely という additional line を Print します。
  • main.lua: FormalPerson module を Require し、input から名前を読み取り、FormalPerson instance を Create して、:introduce() を Call し、両方の behavior が組み合わさった結果を確認します。

input は1つ、person の名前です。

FormalPerson に対して :introduce() を Call すると、Output は2行になります。1行目は parent の method によるもの、2行目は Child による追加です。

{name} says hi
{name} bows politely

たとえば、input が Eleanor の場合、Output は次のようになります。

Eleanor says hi
Eleanor bows politely

ここでの重要なポイントは、FormalPerson が「says hi」のロジックを重複させていないことです。その処理を parent の method に委ねた後、自身の固有の behavior を上に追加しています。これによりコードがすっきりし、Child class が parent の機能を置き換えるのではなく拡張できることが分かります。

自分で試してみよう

-- main.lua: 挨拶システムのエントリーポイント

local FormalPerson = require('FormalPerson')

-- 入力から人物の名前を読み取る
local name = io.read()

-- TODO: 指定された名前でFormalPersonのインスタンスを作成する

-- TODO: FormalPersonインスタンスのintroduceメソッドを呼び出す
quiz icon腕試し

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

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

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