Пытаясь понять этот фрагмент Луа - PullRequest
5 голосов
/ 08 марта 2012

Я пытаюсь понять, что делает эта функция. Кто-нибудь может мне это объяснить?

function newInstance (class)
    local o = {}
    setmetatable (o, class)
    class.__index = class
    return o
end

Это называется так:

self = newInstance (self)

Ответы [ 3 ]

6 голосов
/ 08 марта 2012

Эта функция, очевидно, служит для предоставления варианта ООП в Lua (на мой взгляд, немного небрежно).

Это фабрика для класса.

Она может быть переписана следующим образомДля ясности:

C = { }

C.foo = function(self) -- just some method, so class would not be empty
  print("foo method called", tostring(self))
end

C.__index = C -- (A)

function newInstance(class)
  return setmetatable({ }, class) -- (B)
end

Теперь, если мы создадим два новых экземпляра C, мы ясно увидим, что оба имеют метод foo (), но различаются self:

o1 = newInstance(C)
o1:foo() --> foo method called  table: 0x7fb3ea408ce0

o2 = newInstance(C)
o2:foo() --> foo method called  table: 0x7fb3ea4072f0

The fooметоды одинаковы:

print(o1.foo, o2.foo, o1.foo == o2.foo and "equal" or "different")
--> function: 0x7fb3ea410760    function: 0x7fb3ea410760    equal

Это потому, что таблица C («класс») представляет собой __index ((A) выше) с метатаблицей o1 и o2, установленной в (B).Но o1 и o2 на самом деле две разные таблицы, созданные в (B) («экземпляры классов» или «объекты»).

Примечание: мы устанавливаем C.__index равным C сам по себе (A), поэтому мы будем использовать одну таблицу.Следующее имеет тот же эффект:

prototype = { }

prototype.foo = function(self) -- just some method, so class would not be empty
  print("foo method called", tostring(self))
end

C = { __index = prototype }

function newInstance(class)
  return setmetatable({ }, class)
end

o = newInstance(C)
1 голос
/ 09 марта 2012

Вы не одиноки, мне потребовалось немало времени, чтобы получить этот код. Вот моя интерпретация

каждая таблица может иметь netatable, metatable может хранить среди прочего функции, проиндексированные по имени, а setmetatable устанавливает значение метатаблицы достаточно естественно.

Строка class._index = .., где происходит магия.

Когда вы пытаетесь вызвать функцию с помощью self.fn1 (), тогда lua ищет в себе имя fn1. Если он не может найти его, он ищет в метатализируемой себя таблицу __index и ищет 'fn1' в таблице, хранящейся там.

Теперь метатабелем для себя в вашем примере является класс, поэтому lua ищет в метатаблице (классе) запись __index, чтобы посмотреть, есть ли в этой таблице функция с именем fn1, и она есть, поэтому она возвращается. Вам нужно установить __index для класса обратно на себя, чтобы lua выглядел так же, как и в случае с метафизом - эй, что сбивает с толку.

(кроме того, присваивание __index должно происходить только один раз, но по какой-то причине оно всегда выполняется в новом операторе во всех примерах lua - я беру это вне нового в моих классах - экономит несколько циклов)

Затем вы возвращаете новую таблицу o, lua - это сборщик мусора, поэтому при возврате в local каждый раз создается новая таблица.

function newInstance (class)
    local o = {}
    setmetatable (o, class)
    class.__index = class
    return o
end

НТН

1 голос
/ 08 марта 2012

Используется для достижения объектно-ориентированного поведения в Lua. Lua использует наследование на основе прототипов (аналогично Javascript) вместо наследования на основе классов (например, Java или C ++). Идея состоит в том, что все методы класса реализуются как часть объекта-прототипа, и наследующие объекты делегируются прототипу при вызове.

Например, предположим, что вам нужен класс myClass, предоставляющий метод getMagicNumber:

local myClass = { 
     getMagicNumber = function(self) 
         return self.theNumber;
     end };

local obj = newInstance(myClass);
obj.theNumber = 42;
print(obj:getMagicNumber()); -- supposed to return 42

Это тривиальный пример, но я надеюсь, что вы поняли идею. Происходит следующее: newInstance создает новую таблицу с метатабельной точкой, указывающей на myClass, а также гарантирует, что поле метатаблицы __index также указывает на myClass. Как описано в руководстве Lua по __index, когда вы сейчас пытаетесь вызвать getMagicNumber для этой новой таблицы, происходит следующее: Сначала Lua пытается найти поле getMagicNumber в таблице obj. Поскольку эта таблица пуста, теперь она ищет в этом поле __index (myClass). Поскольку поле находится там, оно теперь вызывает функцию, найденную в myClass.

Программирование на Lua обсуждает этот механизм очень подробно, если вам нужно знать больше.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...