メソッドの継承
CoddyのLuaジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 32/70。
inheritance の link が確立されると、Child class の instance は自動的にすべての Parent methods への access を得ます。これは Lua の lookup chain を通じて行われます。instance に method を call すると、Lua は探しているものを見つけるまで、接続された各テーブルを検索します。
Animal が :breathe() メソッドを定義している、次の設定を考えてみましょう。
local Animal = {}
Animal.__index = Animal
function Animal:new()
local obj = {}
setmetatable(obj, Animal)
return obj
end
function Animal:breathe()
print("Breathing...")
end
-- Dog は Animal を継承する
local Dog = {}
Dog.__index = Dog
setmetatable(Dog, {__index = Animal})
function Dog:new()
local obj = {}
setmetatable(obj, Dog)
return obj
endここで、DogをcreateしてParentのmethodをCallすると何が起こるか見てみましょう:
local buddy = Dog:new()
buddy:breathe() -- 出力: Breathing...Dog class では :breathe() を一度も定義していませんが、それでも動作します。Lua はまず buddy を確認し、何も見つからないため、次に Dog を確認しますが、そこでも見つかりません。そして最後に Animal で見つけます。この自動的な method の継承により、親で共有する動作を一度だけ記述すれば、すべての子 class がすぐにその恩恵を受けられます。
チャレンジ
簡単メソッドの継承を実際に確認するために、シンプルなクリーチャーの階層を作りましょう!Animal親クラスとDog子クラスを作成し、DogインスタンスがAnimalでのみ定義されたメソッドを使用できることを示します。
コードを3つのファイルに分けて整理します。
Animal.lua:標準的なクラスパターンで親クラスをDefineします。動物の名前を保存する:new(name)コンストラクターと、動物の名前の後にmakes a soundを出力する:speak()メソッドを含めます。ファイルの最後でクラスを返します。Dog.lua:Animalから継承する子クラスをDefineします。Animalモジュールをrequireし、DogがAnimalのメソッドにaccessできるように継承のlinkを設定します。名前を保存し、Dogをmetatableとして設定する:new(name)コンストラクターを含めます。Dogクラスは独自の:speak()メソッドをDefineしてはいけません。このメソッドはAnimalから継承されます。main.lua:Dogモジュールをrequireし、inputから名前をreadし、その名前でDogインスタンスをcreateして、インスタンス上で:speak()メソッドをCallします。
1つのinputを受け取ります:犬の名前です。
たとえば、inputがBuddyの場合、出力は次のようになります:
Buddy makes a soundここでのポイントは、Dogクラスが:speak()を一度もDefineしていないにもかかわらず、Dogインスタンス上でCallすると正常に動作することです。LuaはDogインスタンスからDogクラス、さらにメソッドが見つかるAnimalクラスへとlookup chainをたどります。これが継承の動作です!
自分で試してみよう
-- main.lua: エントリーポイント
local Dog = require('Dog')
-- 入力から犬の名前を読み取る
local name = io.read()
-- TODO: 与えられた名前でDogインスタンスを作成する
-- TODO: 犬のインスタンスで:speak()メソッドを呼び出す
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
自分で練習してみよう: Luaオンラインコンパイラ