オブジェクトの結合
CoddyのLuaジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 28/70。
Luaの..演算子は文字列を連結しますが、オブジェクトと文字列を結合したい場合はどうすればよいでしょうか?__concatメタメソッドを使うと、その動作を正確に定義できます。
Luaがa .. bに遭遇し、オペランドの一方に__concatメタメソッドがある場合、その関数を両方の値を引数として呼び出します。これは、オブジェクトを文字列式に自然に組み込みたいときに便利です。
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この関数は、どちらのオペランドが文字列かを確認していることに注目してください。..は"Hello " .. objのようにもobj .. "!"のようにも使えるため、メタメソッドは両方のケースに対応する必要があります。
local person = Name:new("Ada", "Lovelace")
print("Dr. " .. person) -- 出力: Dr. Ada Lovelace
print(person .. " PhD") -- 出力: Ada Lovelace PhDほかの演算子メタメソッドと同様に、__concatは慣例としてドットを付けて記述し、両方のオペランドを引数として受け取ります。算術メタメソッドとの主な違いは、通常、異なる型を組み合わせて扱う点です。オブジェクトと文字列です。
チャレンジ
簡単..演算子を使った文字列式に自然に溶け込めるTitleクラスを作りましょう。敬称や接尾辞を人の肩書きに追加するように、読みやすく直感的な方法でオブジェクトと文字列を組み合わせたいときに便利です。
コードを2つのファイルに分けて整理します。
Title.lua: 肩書きの文字列を格納するtextフィールドを持つTitleクラスを定義します。:new(text)コンストラクターを含め、__concatメタメソッドを実装してください。このメタメソッドでは、文字列がオブジェクトの前にある場合("prefix" .. obj)と、文字列が後ろにある場合(obj .. "suffix")の両方に対応します。結果では、文字列と肩書きのテキストが適切に結合されるようにします。main.lua: Titleモジュールを読み込み、肩書きのインスタンスを作成して、両方向の連結を実演します。
入力は3つ与えられます。
- 肩書きのテキスト(例: "Engineer")
- 肩書きの前に置く接頭辞の文字列(例: "Senior ")
- 肩書きの後ろに置く接尾辞の文字列(例: " III")
メインファイルで、与えられたテキストを使ってTitleを作成します。次に、2つの連結を行い、それぞれの結果を別々の行に出力します。
- 接頭辞の文字列を肩書きオブジェクトと連結する
- 肩書きオブジェクトを接尾辞の文字列と連結する
たとえば、入力がEngineer、Senior 、 IIIの場合、出力は次のようになります。
Senior Engineer
Engineer III1行目には接頭辞と肩書きの結合結果が、2行目には肩書きと接尾辞の結合結果が表示されます。__concatメタメソッドによって、このような自然な文字列の結合が可能になります。
自分で試してみよう
-- 入力を読み取る
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オンラインコンパイラ