Источник: https://habr.com/post/346892/ -- -- Простая реализация класса -- function Class() local class = {} -- Метатаблица для класса. local mClass = {__index = class} -- Функция, которая возвращает "объект" данного класса. function class.instance() return setmetatable({}, mClass) end return class end -- Пока без двоеточий. Rectangle = Class() function Rectangle.new(x, y, w, h) local self = Rectangle.instance() self.x = x or 0 self.y = y or 0 self.w = w or 10 self.h = h or 10 return self end function Rectangle.area(self) return self.w * self.h end -- Инстанцируем rect = Rectangle.new(10, 20, 30, 40) print('rect.area(rect)', rect.area(rect)) --> 1200 print('rect:area()', rect:area()) --> 1200 -- -- Реализация класса с наследованием -- function Class(parent) local class = {} local mClass = {} -- Сам класс будет метатаблицей для объектов. -- Это позволит дописывать ему метаметоды. class.__index = class -- Поля объектов будут искаться по цепочке __index, -- и дотянутся, в том числе, до родительского класса. mClass.__index = parent -- Резервируем поле Super под родителя. class.Super = parent -- Функция, которая будет вызываться при вызове класса function mClass:__call(...) local instance = setmetatable({}, class) -- Резервируем поле класса "init" if type(class.init) == 'function' then -- Возвращаем экземпляр и всё что он вернул функцией init return instance, instance:init(...) end -- Но если её нет - тоже ничего. return instance end return setmetatable(class, mClass) end -- Основной класс. Shape = Class() function Shape:init(x, y) -- в качестве self мы сюда передаём инстанс объекта. self.x = x or 0 self.y = y or 0 return '!!!' end function Shape:posArea() return self.x * self.y end -- Так как таблица Shape является метатаблицей для рождаемых ей объектов, -- мы можем дописывать ей метаметоды. function Shape:__tostring() return '[' .. self.x .. ', ' .. self.y ..']' end local foo, value = Shape(10, 20) print('foo, value', foo, value) --> [10, 20] !!! -- Наследник Rectangle = Class(Shape) function Rectangle:init(x, y, w, h) -- В данный момент, self - это пустая таблица, -- к которой прицеплена таблица Rectangle, как мета. -- Вызов родительских методов через Super. self.Super.init(self, x, y) -- Вызов собственных методов при инициализации - тоже возможен. self.w, self.h = self:getDefault(w, h) end function Rectangle:area() return self.w * self.h end function Rectangle:getDefault(w, h) return w or 10, h or 20 end function Rectangle:__tostring() return '['..self.x..', '..self.y..', '..self.w .. ', '..self.h..']' end rect = Rectangle(10, 20, 30, 40) print('rect', rect) --> [10, 20, 30, 40] print('rect:area()' , rect:area()) --> 30 * 40 = 1200 -- Вызов родительского метода print('rect:posArea()', rect:posArea()) --> 10 * 20 = 200
Lua Справочник v0.05 © 2007-2024 Igor Salnikov aka SunDoctor