Lua学習ノート:対象向け
3379 ワード
Luaにはテーブル(Table)という唯一のデータ構造しか存在しないが,オブジェクト向けの概念を遊ぶことができる.
メンバー関数の追加
よし、C++に詳しいなら似たような進化過程をよく理解する:
独立した
これは、
呼び出し時の
オブジェクトからクラスに昇華
クラスの意味は,1つのオブジェクトの共通点を抽出して量産を実現することである(私はでたらめを言っている><).同様にClass概念を持つJavascriptは
名前の通りMettableもTableであり、metamethodと呼ばれる関数を格納することで、デフォルトの評価動作(文字列として表示する方法、加算方法、接続方法、インデックス方法)を変更できます.Metableの
Mettableを持ち込んだ後:
そして、
継承
継承はオブジェクト向けの大きな特性であり、どのように「クラス」を作成するかが分かったので、継承も明らかになりました.大明湖畔のパラメータ
以上がLuaにおけるオブジェクト指向の実現の基本手法である.
メンバー関数の追加
よし、C++に詳しいなら似たような進化過程をよく理解する:
struct
に関数を追加できるのはCからC++に移行する第一認識だとすれば、Tableに関数を追加することはLuaがどのようにオブジェクトに向かっているかを認識する第一歩と言えるだろう.
player = { health = 200 } --> player ,
function takeDamage(self, amount)
self.health = self.health - amount
end
takeDamage(player, 20) -->
独立した
takeDamage
をplayer
に詰め込むにはどうすればいいですか?答えは直接定義されています.
player = { health = 200 }
function player.takeDamage(self, amount)
self.health = self.health - amount
end
player.takeDamage(player, 20) -->
これは、
player
テーブルにtakeDamage
というフィールドを追加したことに相当します.次のコードと同じです.
player = {
health = 200,
takeDamage = function(self, amount) --> Lua first-class value
self.health = self.health - amount
end
}
player.takeDamage(player, 20) -->
呼び出し時の
player.takeDamage(player,20)
はやや違和感があり(DRYという用語が使われているそうです)、「コロンオペレータ」という専門的な文法糖が出動します.
player:takeDamage(20) --> player.takeDamage(player, 20)
function player:takeDamage(amount) --> function player.takeDamage(self, amount)
オブジェクトからクラスに昇華
クラスの意味は,1つのオブジェクトの共通点を抽出して量産を実現することである(私はでたらめを言っている><).同様にClass概念を持つJavascriptは
prototype
を用いてオブジェクト向けを実現し,LuaはMetableによりprototype
と同様の機能を実現する.
Player = {}
function Player:create(o) --> o
o = o or { health = 200 } --> Lua or || , nil nil
setmetatable(o, self)
self.__index = self
return o
end
function Player:takeDamage(amount)
self.health = self.health - amount
end
playerA = Player:create() --> o nil
playerB = Player:create()
playerA:takeDamage(20)
playerB:takeDamage(40)
名前の通りMettableもTableであり、metamethodと呼ばれる関数を格納することで、デフォルトの評価動作(文字列として表示する方法、加算方法、接続方法、インデックス方法)を変更できます.Metableの
__index
ドメインには「インデックスをどうするか」というメソッドが設定されています.たとえば、foo.bar
が呼び出された場合、foo
にbar
というドメインが見つからない場合、Metable:__index(foo,bar)
が呼び出されます.次のようになります.
playerA:takeDamage(20)
playerA
にはtakeDamge
の関数が存在しないため、Mettableに助けを求める.
getmetatable(playerA).__index.takeDamage(playerA, 20)
Mettableを持ち込んだ後:
Player.__index.takeDamage(playerA, 20)
Player
の__index
はcreate
でself
に指定されているので、最終的には:
Player.takeDamage(playerA, 20)
そして、
takeDamage
のself
は、正しい対象playerA
を得る.継承
継承はオブジェクト向けの大きな特性であり、どのように「クラス」を作成するかが分かったので、継承も明らかになりました.大明湖畔のパラメータ
o
を覚えていますか.
RMBPlayer = Player:create()
function RMBPlayer:broadcast(message) -->
print(message)
end
function RMBPlayer:takeDamage(amount) -->
self.health = self.health - amount / (self.money / 100)
end
vip = RMBPlayer:create { money = 200 } --> ( Table )
vip:takeDamage(20)
vip:broadcast("F*ck")
以上がLuaにおけるオブジェクト指向の実現の基本手法である.