Перейти к содержимому

IncluderWorld

  • записей
    11
  • комментариев
    60
  • просмотра
    30 702

Псевдо ООП для новичков. L1

LeshaInc

3 135 просмотров

Привет! В этом уроке я вас научу псевдо-объектно-ориентированным программированием в Lua. Почему псевдо? А потому-что настоящего ООП в Lua нет, т к классов нет. Приступим!
Для начала напишем класс!

local class = {   -- Создали таблицу    x,    y}class.__index = class     -- Указали индексfunction class:addObject()-- Функция нового объекта    local a = {}    setmetatable(a,self)  -- Наследуем методы    return a              -- Вовращаем таблицу endfunction class:setPos(x,y) -- Установим значения    self.x=x    self.y=yendpixel = class:addObject()pixel:setPos(1,1)        


Теперь вы можете создавать классы.
Enjoy!

  • Нравится 1


4 комментария


Рекомендуемые комментарии

А я дополню, что за хаос творится в коде ;)

 

Начнём по порядку. Сначала мы создаём локальную таблицу class, в который мы указали, что есть x и y как переменные. Так как это у нас будет класс, то будем учиться говорить правильно: это свойства класса. Их можно изменять как в обычной таблице:

class["x"] = 42 -- Способ первый.
class.x = 42    -- Способ второй.

  (отступление 1. Обратите внимание на второй способ: индексирование через точку, как я это называю. Это удобно, когда Вы точно знаете называние поля. Кроме того, это может сэкономить Вам несколько символов при кодинге в БИОСе, но не об этом речь. И есть ещё один нюанс, о котором я расскажу далее)

 

С таблицей мы закончили. Теперь Вам понятна запись class.__index = class. Мы индексируем таблицу class, находя там свойство __index, и присваивая ему значение class. Стоп. Откуда, во-первых, взялся __index, ведь мы же его не указывали! И зачем писать таблицу саму в себя? D:

 

Оказывается (и тут начинается магия ООП), у любой таблицы есть список "скрытых" свойств! В этом уроке рассказывается только об одном из них — индексирование...

 

А давайте не будем бежать впереди паровоза, а то он Вас и задавить может спокойненько, как бы. Познакомимся с понятием "ООП". Это Объектно-Ориентированное Программирование. Такая штука после основательного осмысления может помочь Вам в особо крупных программах, экономя код и нервы. ООП построено по принципу эволюции: сначала создаётся объект, который содержит только базовые функции, затем он наследуется, получая функции своего "родителя", и, вероятно, модифицируясь (убирая, например, некоторые свойства предка и добавляя свои). Сейчас Вы на примере поймёте, о чём я говорю.

 

Пропустим эту строку, и поедем дальше.

function class:addObject() end

Обратите внимание на ":" между class и addObject(). Если бы мы добавляли функцию через точку, то нам пришлось бы дополнительно указывать self в аргументы:

function class.addObject(self) end

Но, согласитесь, это нерационально. ":" же сам вставляет self в аргументы, так что теперь нужно только указывать параметры.

 

Кстати, любая такая функция класса (function someclass:somefunc() end или function someclass.comefunc(self) end называется методом класса)

 

С этим понятно. Рассмотрим код.

local a = {}

Такая строка затруднений вызывать не должна. Но на очереди новая стандартная функция, которая служит для работы с псевдо-ООП: setmetatable()!

 

Она осуществляет наследование, о котором я рассказывал выше. В первый аргумент мы должны указать ссылку на таблицу (попросту, аргумент с таблицей, которая будет "ребёнком"), а во второй — ссылку на таблицу-"родитель". Так как это происходит внутри класса, достаточно указать self. Затем вы возвращаем получившегося "ребёнка".

 

  (Отступление 2. Обычно метод класса, который осуществляет наследование, называется new() или create())

 

Теперь метод setPos(). Помните, мы указывали в таблице свойства x и y? Так вот, чтобы обращаться к методом своего класса, используется всё тот же self. Мы просто устанавливаем для них значения.

 

Фух, с объявлением класса мы закончили. Следующее на очереди: процесс наследования.

 

Наследуем очень просто: someobject = Someclass:new(), например. На так как здесь за создание отвечает addObject(), вызываем его. Мы получили объект pixel. Объект — то, что получилось после наследования класса.

 

И так как произошло наследование, то pixel получил все методы класса.

 

  Оступление 3. И напоследок о "красоте кода".

  • Переменная класса пишется обычно с Заглавной Буквы, слова также отделяются Заглвными Буквами: SomeClass.
  • Метод класса, создающего объект, называется обычно new().

Поделиться комментарием


Ссылка на комментарий

Спасибо, Саша, я в следующих уроках буду рассказывать более подробно. Есть ещё одна фишка в ООП, о которой стоит рассказать на примере лампочек.

Поделиться комментарием


Ссылка на комментарий

Заморачиваете голову юным программистам =)

 

Для наших прикладных задач на этом проекте даже сложно найти применение для такого ООП. Единственное, можно использовать в либах вроде векторов или массивов. Ну или похвастаться как круто вы реализовали приватные методы класса.

 

Я использовал подобные функции в коде векторов.

Хочу обратить особое внимание на вот эту строчку:

setmetatable({new = new, isvector = isvector, zero = zero}, {__call = function(_, ...) return new(...) end}

Не делайте вот этих вот :new() или :addObject()

Во-первых, можно написать код и без двоеточия, и создавать объекты через точку.

Во-вторых, мы же в луа, а не в С++. Есть прекрасный метаметод __call . Зачем создавать класс через какие то дополнительные точки и слова, если можно просто

local c = class()

Рид как то подкидывал ссылку http://habrahabr.ru/post/182018/

Но вообще, на хабре про ООП для ЛУА много чего есть.

Поделиться комментарием


Ссылка на комментарий

Ох тут и каша, я вообще ничего не понял из того, что объяснял тут Сашка Фингер и Леха, что тут налеплено со всего интернета по крупице  вперемешку, сразу не понять простому юзеру, винегрет какой-то если честно.

 

Вячеслав, ты, как опытный программист, можешь на примере, написать 2 класса простых с парочкой методов и свойств, без точек и путаницы, где свойства класса или объекта, где метод через двоеточие и прочее. Что там за одинарные и двойные подчеркивания перед переменными и т.д..А то как так? Мол, не юзайте описания методов, двоеточия и юзайте метаметод _call.  Вот, мол, векторы чьи-то я так юзал, какие-то. Что там можно понять в тех векторах, крипер разбери. Что там Сашка с Лехой поняли и лайкнули, я так и не понял=)

 

Вячеслав, напиши, пожалуйста, в теме Зеро, как оно правильно должно все выглядеть. На примере, 

local c = class()    т.д.

 

Я пока из всей этой абракадабры на ХабрХабре и прочего понял это  как-то так:  РЕДИРЕКТ.

Поделиться комментарием


Ссылка на комментарий

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Добавить комментарий...

×   Вы вставили отформатированное содержимое.   Удалить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отобразить как ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...