программирование в lua, объекты - PullRequest
6 голосов
/ 04 мая 2010

Пример кода:

function Account:new (o)
  o = o or {}   -- create object if user does not provide one
  setmetatable(o, self)
  self.__index = self
  return o
end

взято из:

http://www.lua.org/pil/16.1.html

Какова цель:

self.__index = self

линия? И почему он выполняется каждый раз, когда создается объект?

Ответы [ 5 ]

6 голосов
/ 04 мая 2010

Как уже говорили другие, self (таблица Account) используется в качестве метатаблицы, присваиваемой объектам, созданным с использованием new. Немного упрощаясь (более подробная информация доступна по указанным ссылкам), когда поле не найдено в «o», оно попадает в таблицу «Account», потому что метатабельный o говорит о переходе в Account (это то, что __index делает).

Однако его не нужно выполнять каждый раз, когда создается объект. Вы можете так же легко вставить это куда-нибудь:

Account.__index = Account

и это тоже сработает.

Несколько более длинная история состоит в том, что если у объекта o есть метатабельное, а у этого метатаблицы установлено поле __index, то при поиске поля в o будет использоваться __index найти поле (__index может быть таблицей или функцией). Если o имеет установленное поле, вы не переходите к функции __index его метатаблицы для получения информации. Опять же, я призываю вас читать больше по ссылкам, приведенным выше.

4 голосов
/ 28 июля 2011

Документация Lua по этой детали несколько расплывчата, и многие ответы здесь либо перекликаются с документами Lua, либо не полностью объясняют этот запутанный лакомый кусочек.

Строка self._index = self присутствует исключительно в интересах вновь созданного объекта, o; это не имеет никакого значимого или функционального влияния на Account.

Поле _index имеет особое значение только в контексте метатаблиц; поэтому self._index - это просто старое обычное поле для Account. Однако, когда Account используется в качестве метатаблицы для o, поле _index «становится» метаметодом для o. (Итак, что поле для Account является метаметодом для o.)

Когда вы берете два утверждения в комбинации ...

(1)    setmetatable(o, self)
(2)    self._index = self

... вы используете Account в качестве метатаблицы для o в строке (1) и устанавливаете метаметод _index для o в Account в строке (2). (В строке (2) вы также устанавливаете «обычное старое поле» __index в Account на Account.) Таким образом, полезный аспект self._index = self - это не настройка поля _index для Account, а скорее для настройки _index метаметода для o.

Функционально эквивалентно следующее:

    setmetatable(o, self)
    getmetatable(o)._index = self
3 голосов
/ 04 мая 2010

Lua не является объектно-ориентированным языком, но в нем есть все возможности для написания объектно-ориентированного кода. Тем не менее, это делается в режиме прототипирования в стиле JavaScript . Вместо явного создания классов создается объект-прототип, а затем клонируется для создания новых экземпляров.

Метаметод __index вызывается для выполнения поиска ключей при доступе к таблице, когда ключ еще не присутствует в таблице. Таким образом, self.__index = self по существу позволяет наследовать все методы и поля Account "класса" новым "экземпляром", который создается в строках o = o or {} и setmetatable(o, self).

Смотри также:

0 голосов
/ 06 декабря 2013

Создание объектов (которые просто являются таблицами) совершенно отличается от Lua. Основная идея заключается в создании обычной таблицы, содержащей атрибуты (функции и значения), которые являются общими для всех экземпляров. В этой таблице я назову CAT для таблицы общих атрибутов.

Если вы ссылаетесь на атрибут в таблице и Lua не может найти этот атрибут, есть способ сообщить Lua, где еще искать атрибут. Мы хотим, чтобы Луа посмотрел в КПП общие атрибуты. Метатаблицы отвечают, что нужно. Подробнее о том, как это работает позже.

Нам также нужны методы в CAT, чтобы иметь возможность использовать значения экземпляров. Self ответы, которые нужны. Когда вы вызываете табличную функцию (метод) следующим образом: tableName:methodName(), Lua автоматически помещает ссылку на объект таблицы в качестве первого параметра. Имя этого параметра - self. Даже если метод находится в CAT, self будет ссылаться на конкретную таблицу экземпляров вызывающего объекта.

Скажем, у нас есть кошка под названием Автомобиль.

metaCar = { __index = Car }  
-- this table will be used as the metatable for all instances of Car  
-- Lua will look in Car for attributes it can't find in the instance

Например:

-- instance table is called mustang    
-- setmetatable(mustang, metaCar)

Вот функция общего назначения, которая создает новые объекты экземпляров и устанавливает метатаблицу для нее. Если CAT имеет функцию конструктора (init), она также выполняется.

function newObj(metatable)  
..obj = {}      -- create new empty instance object  
..setmetatable(obj, metatable) –- connect the metatable to it  
..if obj.init then  -- if the CAT has an init method, execute it  
....obj:init()  
..end  
..return obj  
end
0 голосов
/ 04 мая 2010

Они используются для перенаправления доступа к таблицам (локальный y = таблица [ключ]), которые также используются в вызовах методов. В приведенной выше строке объект o будет пытаться получить доступ к ключам, перенаправленным на текущий объект self, без особых усилий наследуя все функции-члены. И, возможно, также переменные данных, в зависимости от того, что именно это __index и как он работает.

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