LÖVE (Love2D) LuaJIT言語編:7.オブジェクトとメソッド

(2018.7.16. 公開)

 Lua/LuaJIT 言語のやや高度な使い方として、「オブジェクト」と「メソッド」がある。LÖVE プログラミングでは必須の考え方なので、ここで解説しておく。

7-1. オブジェクトとは何か

 「オブジェクト」とは、もともと「物体」という意味であるが、Lua/LuaJIT プログラミングでは「互いに関係が深いいくつかのデータと、それを扱うための関数」をひとまとめにしたもののことを指す。データと関数をひとまとめにするため、普通はテーブルを使ってオブジェクトを表現する。LÖVE のように「他のプログラムの一部として Lua/LuaJIT 言語が組み込まれている」場合は、オブジェクトが「他のプログラム」の中で記述されていることがあり、この場合は「ユーザーデータ」型を使ってオブジェクトを表現する。

7-2. オブジェクトのタイプとメソッド

 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

7-3. 親タイプ・子タイプ

 LÖVE でのオブジェクトのタイプは、階層構造になっている。例えば、上に出てきた Image タイプについて言えば、次のような階層構造になっている。

  Object - Drawable - Texture - Image

 この階層で、左にあるものを「親タイプ」と呼ぶ。つまり、Image の親タイプは Texture であり、Texture の親タイプは Drawable であり、Drawable の親タイプは Object である。逆に、右にあるものを「子タイプ」と呼ぶ。

 あるタイプの親タイプは1つしかない。一方、あるタイプの子タイプは、複数あってもよい。例えば、ImageTexture の子タイプであるが、Texture の子タイプには Canvas というものもある。つまり、タイプの階層は、下のような「木」構造になっている。

 タイプが階層構造になっていることには、どういう意味があるのだろうか。実は、2つのタイプが「親・子」の関係になっているとき、「親タイプ」のメソッドはすべて「子タイプ」に引き継がれる。例えば、先ほど述べたように Image の親タイプは Texture なので、Image タイプのオブジェクトは Texture タイプのメソッドも持っていることになる。先ほど例に挙げた getWidth(), getHeight() は、実は Image タイプ独自のメソッドではなく、Texture タイプのメソッドであった。

7-4. モジュール

 オブジェクトとは直接関係ないが、LÖVE のドキュメントに出てくる用語なので、「モジュール」についても簡単に説明しておく。「モジュール」は、関係の深い関数を一つのテーブルにまとめたものである。例えば、love.graphics は LÖVE の1つのモジュールで、グラフィック関連の多くの関数がここに含まれている。先ほど用いた love.graphics.newImage() はその1つであった。

目次