メソッドのオーバーライド
CoddyのLuaジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 37/70。
これまで、child クラスは親クラスのメソッドを継承し、新しいメソッドを追加してきました。しかし、child が同じ method 名で異なる動作を必要とする場合はどうでしょうか?これはmethod のオーバーライドと呼ばれます。
親クラスにある method と同じ名前の method を child class で定義すると、child のバージョンが優先されます。Lua の検索チェーンはまず child class を確認し、そこで method を見つけると検索を停止します。
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 が speak() をオーバーライドする
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()
print(self.name .. " barks: Woof!")
endこれで、各クラスは同じメソッド呼び出しに対して異なる応答をします。
local generic = Animal:new("Creature")
local buddy = Dog:new("Buddy")
generic:speak() -- 出力: Creature が音を出します
buddy:speak() -- 出力: Buddy が吠えます: Woof!Dog の :speak() は、Dog インスタンスに対して親のバージョンを完全に置き換えます。これにより、一貫したインターフェースを維持しながら、特化した動作を作成できます。すべての動物が :speak() を実行できますが、それぞれの種で方法が異なります。
チャレンジ
簡単それぞれ独自の方法で話す、さまざまな生き物が暮らす小さな動物王国を作りましょう!Animal parent classと、親の:speak() methodをそれぞれ独自の動作でオーバーライドする2つの child classes、CatとCowを作成します。
コードを4つのファイルに整理します。
Animal.lua:動物の名前を保存する:new(name)constructorを持つ Base classです。動物の名前の後にmakes a soundを出力する:speak()methodも含めます。これは child classesがオーバーライドする Defaultの動作です。Cat.lua:Animalからinheritsする child classです。その:new(name)constructorでは、parent constructorを呼び出した後、metatableをCatに再リンクします。:speak()methodをオーバーライドし、catsが別の内容を言うようにします。catの名前の後にmeows: Meow!を出力してください。Cow.lua:Animalからinheritsするもう1つの child classです。constructorはCatと同じ方法で設定します。:speak()をオーバーライドし、cowsの名前の後にmoos: Moo!を出力します。main.lua:everythingをまとめます!inputから2つの名前を読み取り、firstの名前でCatを、secondの名前でCowをCreateし、その後それぞれに:speak()をCallして、同じmethod名でもclassによって異なる出力になることを示します。
2つのinputを受け取ります。
- catの名前
- cowの名前
mainファイルで両方の動物を作成し、最初にcat、followed by cowの順で:speak()をCallします。
たとえば、inputがWhiskersとBessieの場合、出力は次のようになります。
Whiskers meows: Meow!
Bessie moos: Moo!どちらの動物も同じ:speak() methodの呼び出しに応答しますが、それぞれ自分のtypeに固有の出力を生成することに注目してください。Catのバージョンは、parentの genericな "makes a sound"動作を完全に置き換え、Cowのバージョンも同様です。これが実際のmethod overridingです。同じinterface、異なるimplementationsです。
自分で試してみよう
-- main.lua: すべてをまとめる
local Cat = require('Cat')
local Cow = require('Cow')
-- 入力を読み取る
local catName = io.read()
local cowName = io.read()
-- TODO: 最初の名前で Cat を作成する
-- TODO: 2番目の名前で Cow を作成する
-- TODO: まず cat に対して :speak() を呼び出し、次に cow に対して呼び出す
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
自分で練習してみよう: Luaオンラインコンパイラ