(2018.7.16. 公開)
Lua/LuaJIT 言語のやや高度な使い方として、「オブジェクト」と「メソッド」がある。LÖVE プログラミングでは必須の考え方なので、ここで解説しておく。
「オブジェクト」とは、もともと「物体」という意味であるが、Lua/LuaJIT プログラミングでは「互いに関係が深いいくつかのデータと、それを扱うための関数」をひとまとめにしたもののことを指す。データと関数をひとまとめにするため、普通はテーブルを使ってオブジェクトを表現する。LÖVE のように「他のプログラムの一部として Lua/LuaJIT 言語が組み込まれている」場合は、オブジェクトが「他のプログラム」の中で記述されていることがあり、この場合は「ユーザーデータ」型を使ってオブジェクトを表現する。
LÖVE では多くのオブジェクトが使用される。これらは、「タイプ」で分類されている。同じタイプのオブジェクトは、同じ種類のデータと、同じ関数を所有している。データの中身はオブジェクトごとに異なるが、関数は共通である。(一般的な「オブジェクト指向プログラミング」では、オブジェクトのタイプのことを「クラス」と呼ぶことが多いが、ここでは LÖVE のドキュメントに合わせて「タイプ」と呼ぶことにする。)
たとえば、入門編の「5.キャラクタを表示する」で用いた love.graphics.newImage()
関数は、Image
タイプのオブジェクトを返す。
fish0 = love.graphics.newImage('fish0.png')
man0 = love.graphics.newImage('man0.png')
-- fish0, man0 は Image タイプのオブジェクト
fish0
, man0
はどちらも同じ Image
タイプのオブジェクトなので、共通の関数を所有している。例えば、次のような関数である。
fish0:getWidth() -- 画像の幅を返す
fish0:getHeight() -- 画像の高さを返す
man0:getWidth() -- 関数の中身は fish0:getWidth() と同じ
man0:getHeight() -- 関数の中身は fish0:getHeight() と同じ
上の関数は、コロンを使った「メソッド呼び出し」の形式で記述してある。オブジェクトが所有している関数のことを「メソッド」と呼ぶ。メソッドは、通常はそのオブジェクトのデータに対して何らかの処理を行うものである。このため、メソッドには必ず最初の引数として、オブジェクト自体を渡すことになっている。
「関数呼び出し」のところで述べた通り、上のメソッド呼び出しは、下のような(コロンなしの)関数呼び出しと等価である。
fish0.getWidth(fish0) -- コロンなし、最初の引数が fish0
fish0.getHeight(fish0) -- コロンなし、最初の引数が fish0
man0.getWidth(man0) -- コロンなし、最初の引数が man0
man0.getHeight(man0) -- コロンなし、最初の引数が man0
LÖVE でのオブジェクトのタイプは、階層構造になっている。例えば、上に出てきた Image
タイプについて言えば、次のような階層構造になっている。
Object - Drawable - Texture - Image
この階層で、左にあるものを「親タイプ」と呼ぶ。つまり、Image
の親タイプは Texture
であり、Texture
の親タイプは Drawable
であり、Drawable
の親タイプは Object
である。逆に、右にあるものを「子タイプ」と呼ぶ。
あるタイプの親タイプは1つしかない。一方、あるタイプの子タイプは、複数あってもよい。例えば、Image
は Texture
の子タイプであるが、Texture
の子タイプには Canvas
というものもある。つまり、タイプの階層は、下のような「木」構造になっている。
タイプが階層構造になっていることには、どういう意味があるのだろうか。実は、2つのタイプが「親・子」の関係になっているとき、「親タイプ」のメソッドはすべて「子タイプ」に引き継がれる。例えば、先ほど述べたように Image
の親タイプは Texture
なので、Image
タイプのオブジェクトは Texture
タイプのメソッドも持っていることになる。先ほど例に挙げた getWidth()
, getHeight()
は、実は Image
タイプ独自のメソッドではなく、Texture
タイプのメソッドであった。
オブジェクトとは直接関係ないが、LÖVE のドキュメントに出てくる用語なので、「モジュール」についても簡単に説明しておく。「モジュール」は、関係の深い関数を一つのテーブルにまとめたものである。例えば、love.graphics
は LÖVE の1つのモジュールで、グラフィック関連の多くの関数がここに含まれている。先ほど用いた love.graphics.newImage()
はその1つであった。
目次