コロナのテーブルとメタテーブルの違いは何ですか?メタテーブルの種類は何ですか?どこでどのように使用できますか?テーブルとメタテーブルを使用する主な目的は何ですか?
2 に答える
Luaのテーブルは、動的な構造化データを作成するために使用できる主なデータ型です。他の言語には配列、リスト、辞書(Key-Valueストレージ)があり、Luaにはテーブルしかありません。基本テーブルで実行できる唯一の操作は、tab[key]
構文を使用して値にインデックスを付けて格納することです。
local tab = {}
tab['key1'] = 'Hello' -- storing a value using a string key
tab.key2 = 'World' -- this is syntax sugar, equivalent to previous
print(tab.key1, tab['key2']) -- indexing, the syntax is interchangable
基本的なテーブルでは、他に何もできません。たとえば、次のように追加します。
local v1={x=0,y=0}
local v2={x=1,y=1}
print(v1+v2)
--> stdin:1: attempt to perform arithmetic on local 'v1' (a table value)
メタテーブルを使用すると、テーブルの動作を変更したり、テーブルの追加、乗算、連結()などを行うときに何を実行するかを指定できます。メタテーブルは..
、メタメソッドとも呼ばれる特別なキーを持つ関数を含む単なるテーブルです。を使用して、メタテーブルをテーブルに割り当てることができますsetmetatable()
。例えば:
local Vector = {} -- this will be the metatable for vectors
function Vector.__add(v1, v2) -- what to do when vectors are added
-- create a new table and assign it a Vector metatable
return setmetatable({x=v1.x+v2.x, y=v1.y+v2.y}, Vector)
end
function Vector.__tostring(v) -- how a vector should be displayed
-- this is used by tostring() and print()
return '{x=' .. v.x .. ',y=' .. v.y .. '}'
end
local v1 = setmetatable({x=1, y=2}, Vector)
local v2 = setmetatable({x=3, y=4}, Vector)
-- vectors are added and the resulting vector is printed
print(v1 + v2) --> {x=4,y=6}
メタテーブルをよりよく理解したい場合は、メタテーブルに関するLuaのプログラミングの章を必ず読んでください。
Lua(Coronaのベースとなる言語)は、さまざまな目的でメタテーブルを使用します。
マニュアルの関連するエントリはセクション2.8です。素敵なチュートリアルはここまたはここにあります。
メタテーブルは他のテーブルと同じですが、別のテーブルでメタテーブルとして設定されます(2つのテーブルを区別するために、これをベーステーブルと呼びます)。
メタテーブルには何でも含めることができますが、特別なキー(二重アンダースコアで始まる)は興味深いものです。このテーブルでこのキーに設定された値は、特別な機会に呼び出されます。どの機会がどのキーに依存します。最も興味深いのは次のとおりです。
__index
:ベーステーブルのキーが検索されるたびに使用されますが、存在しません。これには、代わりにキーが検索されるテーブル、または元のテーブルとキーが渡される関数のいずれかを含めることができます。これは、テーブルへのメソッドの実装(OOPスタイル)、リダイレクト、フォールスルーケース、デフォルトの設定などに使用できます。__newindex
:テーブルに新しいキーが割り当てられる場合は常に使用されます(以前はnilでした)。テーブルの場合、キーはそのテーブルに割り当てられます。関数の場合、その関数には元のテーブル、キー、および値が渡されます。これは、テーブルへのアクセスの制御、データの前処理、割り当てのリダイレクトに使用できます。__call
:たとえば、を使用する場合に呼び出される関数を設定できます。table()
。__add,__sub,__mul,__div,__mod
二項演算を実装するために使用され、__unm
単項演算を実装するために使用され、__concat
連結を実装するために使用されます(..演算子)__len
長さ演算子(#)を実装するために使用されます__eq,__lt,__le
比較を実装するために使用されます
__index&co。を使用するときに知っておくべき小さなこと:これらのメソッドでは、メタメソッドが毎回呼び出されてループが発生するのを防ぐために、rawgetとrawsetを使用する必要があります。小さな例として:
t={1,2,3} -- basetable
mt={} -- metatable
mt.__index=function(t,k)
print("__index event from "..tostring(t).." key "..k)
return "currently unavailable"
end
mt.__newindex=function(t,k,v)
print("__newindex event from "..tostring(t).." key: "..k.." value: "..v)
if type(k)=="string" then
rawset(t,k,v:reverse())
else
rawset(t,k,v)
end
end
mt.__call=function(t,...)
print("call to table "..tostring(t).." with arguments: ".. table.concat({...},','))
print("All elements of the table:")
for k,v in pairs(t) do print(k,v) end
end
setmetatable(t,mt)
t[4]="foo" -- this will run the __newindex method
print(t[5]) -- this will run the __index method
t("foo","bar")
-- Multiple fall through example:
t={}
mt={}
mt2={}
setmetatable(t,mt) -- metatable on base table
setmetatable(mt,mt2) -- second layer of metatable
mt.__index=function(t,k) print('key '..k..' not found in '..namelookup[t]) return getmetatable(t)[k] end -- tries looking nonexistant indexes up in mt.
mt2.__index=mt.__index -- function was written portably, reuse it.
t[1]='A'
mt[2]='B'
mt2[3]='C'
namelookup={[t]="t",[mt]="mt",[mt2]="mt2"}
print(t[1],t[2],t[3],t[4])
これらはばかげた例に過ぎませんが、もっと複雑なことを行うことができます。例を見て、Luaでのプログラミングの関連する章を見て、実験してください。そして、混乱しないようにしてください;)