2

方法/1

Dog = {}
function Dog:new()
  local newObj = {sound = 'woof'}
  return setmetatable(newObj,   { __index = self })
end

方法/2

Dog = {}
function Dog:new()
  local newObj = {sound = 'woof'}
  self.__index = self
  return setmetatable(newObj, self)
end

ほとんどの場合、このself.__index = self方法を使用している人を見てきましたが、これは不器用に思えます。Dogメタテーブルを構成しないすべての追加メソッドを含むオブジェクト全体を に渡すのはなぜsetmetatableですか? メソッド/1metatable.__indexは、新しいオブジェクトをオブジェクトに設定するのに適していDogます。また、クリーンでもあります。

Method/1の代わりにMethod/2を使用する正当な理由はありますか?


コンテキストを提供するためのいくつかの追加コード。両方の方法で動作します

function Dog:makeSound()
  print('I say ' .. self.sound)
end

mrDog = Dog:new()
mrDog:makeSound()
4

3 に答える 3

1

メタメソッドが必要な場合は__eq、すべてのインスタンス間でメタテーブルを 1 つだけ共有する必要があります。そうしないと機能しません。この場合、方法 1 は機能しません。

しかし、メタテーブルは である必要はなくDog、専用のメタテーブルにすることができます:

方法 3.

Dog = {}
local DogMeta = {__index = Dog}
function Dog:new(name)
  local newObj = {sound = 'woof', name = name}
  return setmetatable(newObj, DogMeta)
end
function DogMeta.__eq(dog1, dog2)
  return dog1.name == dog2.name
end
于 2013-12-13T04:52:58.403 に答える
1

どちらのアプローチも同じ最終的な動作を実現しますが、「作成よりもリソースをリサイクルする」ポリシーにより適しているため、方法 2 を好む人がいるかもしれません。方法 2Dogでは、作成する Dog オブジェクトの数に関係なく、常に 1 つのテーブルをメタテーブルとして使用します。方法 1 の OTOH は、作成されたすべての Dog オブジェクトのメタとして機能するためだけに、新しい匿名テーブルを作成します。

ただし、方法 1 は、メタテーブルとオブジェクト定義の懸念が混在していないため、言語の初心者にとっておそらく読みやすく、理由付けが簡単です。

于 2013-12-13T02:38:54.493 に答える