継承のセットアップ
CoddyのLuaジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 31/70。
これまで、各オブジェクトが単一のプロトタイプテーブルでメソッドを検索するクラスを構築してきました。しかし、あるクラスを別のクラスに基づいて構築したい場合はどうでしょうか?ここでinheritanceの出番です。子クラスは親クラスのすべてにアクセスしながら、独自の機能を追加できます。
重要なポイントは、クラステーブル自体がメタテーブルを持てるということです。Lua は子クラス内で何かを見つけられないと、子クラスのメタテーブルの __index を調べます。これは親クラスを指しています。
-- 親クラス
local Animal = {}
Animal.__index = Animal
function Animal:new()
local obj = {}
setmetatable(obj, Animal)
return obj
end
function Animal:breathe()
print("Breathing...")
endこれが継承の設定です。子クラスを作成し、そのメタテーブルが親を参照するように設定します。
-- 子クラス
local Dog = {}
Dog.__index = Dog
setmetatable(Dog, {__index = Animal})この1行、setmetatable(Dog, {__index = Animal})がinheritanceのリンクを作成します。DogのinstanceがDogに見つからないmethodを呼び出すと、LuaはAnimalを確認します。
検索チェーンは次のように機能します: instance → Dog → Animal。各ステップでは、次に検索するテーブルを見つけるために __index を使用します。これにより、子クラスはメソッドをコピーしなくても、すべての親メソッドを自動的に継承できます。
チャレンジ
簡単初めての継承階層を作ってみましょう!ここでは、Machine クラスを基底クラスとし、そこから Robot クラスが継承する、シンプルな親子クラス関係を作成します。
コードは3つのファイルに分けて整理します。
Machine.lua:標準的なクラスパターンを使って親クラスを定義します。:new()コンストラクターと、Machine is operationalと出力する:status()メソッドを含めます。__indexの設定と、ファイル末尾でのクラスの返却も忘れないでください。Robot.lua:Machine を継承する子クラスを定義します。Machine モジュールを Require し、独自の__indexを持つ Robot テーブルを設定し、setmetatable(Robot, {__index = Machine})を使って継承リンクを確立します。Robot をメタテーブルとする instance を作成する:new()コンストラクターを含めます。main.lua:Robot モジュールを Require し、Robot の instance を作成して、inherited した:status()method を呼び出すことで、すべてをまとめます。
ここでの重要な概念は、Robot クラス自体は :status() を定義していないということです。メタテーブルチェーンを通じて、この method を Machine から継承します。Robot の instance に対して :status() を呼び出すと、Lua はまず Robot 内を探します。そこで見つからない場合は、__index リンクをたどって Machine へ進み、そこで method を見つけます。
出力は次のようになります。
Machine is operationalこの1行によって、inheritance が機能していることが証明されます。Robot は、親クラスでのみ定義された method に正常にアクセスできました!
自分で試してみよう
-- main.lua: すべてをまとめる
-- TODO: Robotモジュールをrequireする
-- TODO: Robot:new()を使ってRobotインスタンスを作成する
-- TODO: ロボットインスタンスで継承された:status()メソッドを呼び出す
-- This should print "Machine is operational"
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
自分で練習してみよう: Luaオンラインコンパイラ