文字列のフォーマット
CoddyのLuaジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 16/70。
オブジェクトを直接 printすると、Lua は table: 0x55a... のような役に立たない情報を表示します。単なるメモリアドレスです。__tostring metamethod を使うと、オブジェクトを印刷したりテキストに変換したりするときに、どの文字列で表すかを正確に定義できます。
classパターンでは、classテーブルに__tostringをfunctionとして追加します。class自体がinstancesのmetatableとして機能するため、Luaはこのfunctionを自動的に見つけて使用します。
local Player = {}
Player.__index = Player
function Player:new(name, level)
local instance = {}
setmetatable(instance, self)
instance.name = name
instance.level = level
return instance
end
function Player:__tostring()
return "Player: " .. self.name .. " (Level " .. self.level .. ")"
endこれで、Player インスタンスを print すると、Lua は自動的に __tostring method を呼び出します。
local hero = Player:new("Luna", 5)
print(hero) -- 出力: Player: Luna (Level 5)__tostring はコロン構文を使用し、self を受け取るため、すべてのインスタンスデータにアクセスできます。この関数は文字列を返す必要があります。オブジェクトにとって意味のある方法でフォーマットし、任意の属性を組み合わせて読みやすい表現にできます。
チャレンジ
簡単自分自身を紹介する方法を知っている Book クラスを作ってみましょう!本を直接出力すると、Lua はわかりにくいメモリアドレスの代わりに、きれいに整形された文字列を表示します。これはすべて __tostring metamethod のおかげです。
コードを2つのファイルに分けて整理します。
Book.lua: 標準的な prototype パターンを使ってBookクラスを Define します。それぞれの本にはtitleとauthorを保存します。:new(title, author)Constructor を含め、本を出力したときに読みやすい形式で情報が表示されるように__tostringmetamethod を Implement します。main.lua: Book module を Require し、本の instances を作成して直接出力し、独自の文字列フォーマットが実際に動作することを確認します。
__tostring method は、次の正確な形式の文字列を返す必要があります。
"[title]" by [author]出力文字列では title が double quotes で囲まれていることに注意してください。
4つの入力を受け取ります。
- 1冊目の本の Title
- 1冊目の本の author
- 2冊目の本の Title
- 2冊目の本の author
main ファイルで、提供された inputs を使って2冊の本を作成し、それぞれの本を直接出力します(method を呼び出すのではなく、単に print(book) を使います)。各本はそれぞれ1行に表示される必要があります。
たとえば、入力が The Hobbit、J.R.R. Tolkien、1984、George Orwell の場合、出力は次のようになります。
"The Hobbit" by J.R.R. Tolkien
"1984" by George Orwell__tostring は string を return する必要があり、さらにクラス table が instances の metatable として機能するため、本を出力すると Lua は自動的に __tostring function を見つけて使用することを Remember してください。
自分で試してみよう
-- Bookモジュールを読み込む
local Book = require('Book')
-- 入力を読み取る
local title1 = io.read()
local author1 = io.read()
local title2 = io.read()
local author2 = io.read()
-- TODO: Book:new()を使って2つの本のインスタンスを作成する
-- TODO: 各本を直接出力する(print(book)を使うだけ)
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
自分で練習してみよう: Luaオンラインコンパイラ