0Pricing
Lua Academy · レッスン

superによる親メソッドの呼び出し

基底クラスのメソッドを明示的に呼び出し、協調的な初期化を行います。

「superによる親メソッドの呼び出し」はCoddyKit上の無料Lua Academyレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはLua Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Lua Academyコースには全4レッスンが含まれています。

スーパー呼び出しが必要な理由

子が親のメソッドを上書きしながら親のロジックも必要とする場合、親メソッドを明示的に呼び出します。Luaにはsuperキーワードがないため、親テーブルを直接参照します:Parent.method(self, args)。

local Base={}
Base.__index=Base
function Base:describe()
  return "Base[name="..self.name.."]"
end

local Child={}
Child.__index=Child
setmetatable(Child,{__index=Base})

function Child:describe()
  local parentDesc = Base.describe(self)  -- super call
  return parentDesc .. " + Child[extra=true]"
end

local c=setmetatable({name="X"},Child)
print(c:describe())

コンストラクターでのsuper

子コンストラクターはParent.new()またはParent._init(self,...)を通じて親コンストラクターを呼び出します。これにより、すべての子インスタンスで親の初期化が実行されます。

local Animal={}
Animal.__index=Animal
function Animal._init(self,name,sound)
  self.name=name; self.sound=sound; self.alive=true
end

local Dog={}
Dog.__index=Dog; setmetatable(Dog,{__index=Animal})
function Dog.new(name,breed)
  local self=setmetatable({},Dog)
  Animal._init(self,name,"Woof")  -- super init
  self.breed=breed
  return self
end

local d=Dog.new("Rex","Lab")
print(d.name,d.sound,d.breed)

協調的な初期化

深い階層では、各レベルが自身のフィールドだけを初期化し、親のinitを呼び出します。これにより、各クラスが自分のフィールドだけに責任を持てます。

local A={}
function A._init(self,x) self.x=x end

local B={}
function B._init(self,x,y) A._init(self,x); self.y=y end

local C={}
C.__index=C
function C.new(x,y,z)
  local self=setmetatable({},C)
  B._init(self,x,y)
  self.z=z
  return self
end

local c=C.new(1,2,3)
print(c.x,c.y,c.z)  -- 1 2 3

superラッパー

super(self)ヘルパーを作成し、selfを渡して親メソッドを呼び出すプロキシオブジェクトを返します。これにより、Parent.method(self, ...)よりもすっきりした構文を使えます。

local function super(self)
  local mt = getmetatable(getmetatable(self).__index)
  if mt then
    return setmetatable({}, {__index=function(_,k)
      local parentCls = mt.__index or mt
      return function(...) return parentCls[k](self,...) end
    end})
  end
end
print("super() helper pattern shown")

複数のレベル

継承レベルが複数ある場合、各レベルは直上の親を呼び出します。チェーンは自動的に伝播します。

local L1={} L1.__index=L1
function L1:intro() return "L1" end

local L2={} L2.__index=L2
setmetatable(L2,{__index=L1})
function L2:intro() return L1.intro(self).."+L2" end

local L3={} L3.__index=L3
setmetatable(L3,{__index=L2})
function L3:intro() return L2.intro(self).."+L3" end

local obj=setmetatable({},L3)
print(obj:intro())  -- L1+L2+L3

メソッドの拡張

親メソッドを拡張するには、親版を呼び出してから追加の動作を実行します。これは、正式なAOPフレームワークを使わずに行う「前処理」または「後処理」のアドバイスです。

local Logger={} Logger.__index=Logger
function Logger:log(msg) print("[LOG] "..msg) end

local TimedLogger={} TimedLogger.__index=TimedLogger
setmetatable(TimedLogger,{__index=Logger})

function TimedLogger:log(msg)
  local ts=os.date("%H:%M:%S")
  Logger.log(self,"["..ts.."] "..msg)  -- augment
end

local tl=setmetatable({},TimedLogger)
tl:log("Server started")

superの落とし穴を避ける

super呼び出しでは、getmetatable(self).__indexではなく、必ず正確な親クラス名を使用してください。メタテーブル検索では真の親ではなく中間クラスが返されることがあります。明確さと正確性のため、明示的に指定してください。

-- Correct: explicit parent reference
function Child:init(x)
  Base.init(self, x)  -- explicit, clear
end

-- Fragile: uses metatable lookup
function Child:initBad(x)
  local parent = getmetatable(getmetatable(self).__index)
  -- This may not be Base if hierarchy changes!
end
print("Be explicit with parent class references")

__tostringでのsuper

子クラスで__tostringを上書きし、完全な説明になるように親の表現も含めます。

local Base={}
Base.__index=Base
Base.__tostring=function(self) return "Base("..self.name..")" end

local Child={}
Child.__index=Child
setmetatable(Child,{__index=Base})
Child.__tostring=function(self)
  local baseStr = Base.__tostring(self)
  return baseStr.." + Child(level="..self.level..")"
end

local c=setmetatable({name="X",level=5},Child)
print(tostring(c))  -- Base(X) + Child(level=5)

保護されたテンプレートメソッド

テンプレートメソッドパターンでは、基底クラスが抽象的な手順の呼び出しを含むアルゴリズムの骨格を定義し、サブクラスがその手順を実装します。

local Processor={} Processor.__index=Processor
function Processor:run(data)
  data = self:preProcess(data)
  data = self:process(data)
  return self:postProcess(data)
end
function Processor:preProcess(d) return d end
function Processor:postProcess(d) return d end
function Processor:process(d) error("implement process()") end

local Upper={} Upper.__index=Upper
setmetatable(Upper,{__index=Processor})
function Upper:process(d) return d:upper() end

local p=setmetatable({},Upper)
print(p:run("hello"))  -- HELLO

super呼び出しの慣例

慣例として、内部専用のinit関数には_を接頭辞として付け(例:_init)、公開するnew()は最上位のコンストラクターだけに用意します。これにより継承チェーンをすっきり保てます。

-- Convention summary:
-- Animal._init(self, ...)  -- used for super calls
-- Dog.new(...)             -- only public constructor
-- Never call Dog._init from outside

local Foo={} Foo.__index=Foo
function Foo._init(self,x) self.x=x end
function Foo.new(x)
  return setmetatable({},Foo):_init(x) or
    (function() local s=setmetatable({},Foo); Foo._init(s,x); return s end)()
end
print("Convention: _init for super, new() for public")

スーパー呼び出しに関する質問

Luaで親メソッドを呼び出すにはどうしますか?

復習:スーパー呼び出し

親メソッドは必ず明示的なクラス参照で呼び出します:Parent.method(self, ...)。継承レベルをまたぐ協調的なコンストラクターには、_initの慣例を使用します。

よくある質問

「superによる親メソッドの呼び出し」レッスンは無料ですか?

はい。「superによる親メソッドの呼び出し」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Lua Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Lua Academyコースには全4レッスンが含まれています。

「superによる親メソッドの呼び出し」で何を学びますか?

基底クラスのメソッドを明示的に呼び出し、協調的な初期化を行います。 ブラウザで直接実行するハンズオンコードでLua Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Lua Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのLua Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。

「superによる親メソッドの呼び出し」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このLua Academyレッスンでコードを書いて実行できますか?

はい。すべてのLua Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. __indexチェーンによる単一継承
  2. superによる親メソッドの呼び出し
  3. Mixinパターン
  4. オーバーライドとポリモーフィズム
← Lua Academyに戻る