オブジェクトの結合
CoddyのLuaジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 28/70。
Luaの..演算子は文字列を連結しますが、オブジェクトと文字列を組み合わせたい場合はどうすればよいでしょうか?__concatメタメソッドを使うと、これをどのように動作させるかを正確に定義できます。
Lua が a .. b に遭遇し、一方の operand に __concat metamethod がある場合、両方の値を引数としてその function を呼び出します。これは、object を string 式に自然に組み込みたい場合に便利です。
local Name = {}
Name.__index = Name
function Name:new(first, last)
local obj = {first = first, last = last}
setmetatable(obj, Name)
return obj
end
function Name.__concat(a, b)
if type(a) == "string" then
return a .. b.first .. " " .. b.last
else
return a.first .. " " .. a.last .. b
end
endこの function はどの operand が string かを確認していることに注目してください。.. は "Hello " .. obj または obj .. "!" として使用できるため、metamethod は both cases を handle する必要があります。
local person = Name:new("Ada", "Lovelace")
print("Dr. " .. person) -- 出力: Dr. Ada Lovelace
print(person .. " PhD") -- 出力: Ada Lovelace PhD他の演算子 metamethods と同様に、__concat はドット構文を使用し、引数として both operands を受け取ります。算術 metamethods との主な違いは、通常、異なる型を組み合わせて扱う点です。あなたの object と string です。
チャレンジ
簡単Title クラスを作成し、.. 演算子を使って文字列式に自然に組み込めるようにしましょう。これは、人の肩書きに敬称や suffix を追加するように、オブジェクトと文字列を読みやすく直感的な方法で組み合わせたい場合に便利です。
コードは 2 つのファイルに分けて整理します。
Title.lua:肩書きの文字列を格納するtextフィールドを持つ Title クラスを定義します。:new(text)Constructor を含め、__concatmetamethod を Implement します。metamethod は、文字列がオブジェクトの前に来る場合("prefix" .. obj)と、文字列が後に来る場合(obj .. "suffix")の両方を handle する必要があります。result は、文字列と肩書きの text を適切に組み合わせるものにします。main.lua:Title module を Require し、肩書きの instance を Create して、両方向の連結を示します。
3 つの inputs を受け取ります。
- 肩書きの text(例: "Engineer")
- 肩書きの前に置く prefix string(例: "Senior ")
- 肩書きの後に置く suffix string(例: " III")
main file で、given の text を使って Title を Create します。次に 2 つの連結を実行し、それぞれの result を別々の行に print します。
- prefix string と Title object を Concatenate する
- Title object と suffix string を Concatenate する
たとえば、inputs が Engineer、Senior 、 III の場合、Output は次のようになります。
Senior Engineer
Engineer III1 行目には prefix と肩書きの組み合わせが、2 行目には肩書きと suffix の組み合わせが示されます。__concat metamethod によって、このような自然な string の組み合わせが可能になります。
自分で試してみよう
-- 入力を読み取る
local titleText = io.read()
local prefix = io.read()
local suffix = io.read()
-- Titleモジュールを読み込む
local Title = require('Title')
-- TODO: 与えられたtitleTextでTitleインスタンスを作成する
-- TODO: prefixをtitleオブジェクトと連結して結果を出力する
-- TODO: titleオブジェクトをsuffixと連結して結果を出力する
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
自分で練習してみよう: Luaオンラインコンパイラ