Автор: Setuper 27.12.2008, 15:44
Продолжаю знакомство с ООП в LUA.
Реализация класса в lua.
- Конструкторы
- Открытые переменные и функции (public)
- Закрытые переменные и функции (private)
Код
--//Функция-конструктор класса cMyClass
cMyClass = function(tData)
local t = {}
tData = tData or {}
--//private:
t.z = 0 --//Значение по умолчанию
t.PrivateFunc = function()
return "Это закрытая функция, которая доступна только внутри данного класса cMyClass!"
end
--//public:
tData.x = tData.x or 0
tData.y = tData.y or 0
--//Инициализация полей 'x' и 'y'
t.__call = function(f, a, b)
if a then tData.x = a end
if b then tData.y = b end
end
--//Получения значения индекса
t.__index = function(tab, key)
if key == "z" then --//Защита от чтения 'private' переменной 'z'
return
elseif key == "GetZ" then --//Объявление 'public' функции, которая возвращает значание 'private' переменной 'z'
return function()
return t.z
end
elseif key == "SetZ" then --//Объявление 'public' функции, которая записывает значание в 'private' переменную 'z'
return function(z)
t.z = z
return true
end
elseif key == "x" then --//Доступ к 'public' полю 'x'
return tData.x or 0
elseif key == "y" then --//Доступ к 'public' полю 'y'
return tData.y or 0
elseif rawget(tab, key) then --//Доступ к любому другому 'public' полю
return rawget(tab, key)
end
end
--//Присвоение новому индексу значения
t.__newindex = function(tab, key, val)
if key == "z" then --//Защита от записи в 'private' переменную 'z'
return
else --//Запись в любое другое поле
return rawset(tab, key, val)
end
end
setmetatable(tData, t)
return tData
end
Использование класса cMyClass
Код
--//Создаём объект 'u' типа 'cMyClass' с 'public' полем 'z'
local u = cMyClass({z="u.z_value"})
--//Создаём объект 'v' типа 'cMyClass' с 'public' полями 'x' и 'y'
local v = cMyClass({x="v.x_value",y="v.y_value"})
--//Инициализируем 'public' поля 'x' и 'y' объекта 'u'
u("u.x_value", "u.y_value")
--//Устанавливаем значение 'private' поля 'z' объекта 'u'
u.SetZ("private_z_value")
--//Выводим результаты
Core.SendToAll("\n==============================================\n\t"..
"u.x = '"..tostring(u.x).."', \tv.x = '"..tostring(v.x).."';\n\t"..
"u.y = '"..tostring(u.y).."', \tv.y = '"..tostring(v.y).."';\n\t"..
"u.z = '"..tostring(u.z).."', \tv.z = '"..tostring(v.z).."';\n\t"..
"u.GetZ() = '"..tostring(u.GetZ()).."', \tv.GetZ() = '"..tostring(v.GetZ()).."'.\n"..
"==============================================")
Автор: Setuper 25.2.2009, 21:22
Универсальная функция для создания класса в lua.
Включает в себя аппарат простого и множественного наследования.
Для множественного наследования используется несколько раз простое наследование.
Код
local function concat(p1, p2)
local t = {}
for k, v in pairs(p1) do
t[k] = v
end
for k, v in pairs(p2) do
t[k] = v
end
if next(p1.__parent or {}) or next(p2.__parent or {}) then
t.__parent = concat(p1.__parent or {}, p2.__parent or {})
end
return t
end
class = function(...)
local t, m = {}, {}
_G.setmetatable(t, m)
for i = 1, _G.select('#', ...) do
local el = _G.select(i, ...)
if _G.type(el) == 'table' then
for k, v in _G.pairs(el) do
t[k] = v
end
end
end
t.__parent = m
m.__call = function(self, ...)
local t, mt_old, mt_new = {}, {}, {}
for k, v in pairs(getmetatable(self) or {}) do
mt_old[k] = v
end
for k, v in pairs(self) do
mt_old[k] = v
end
for i = 1, _G.select('#', ...) do
local el = _G.select(i, ...)
if _G.type(el) == 'table' then
for k, v in pairs(getmetatable(el) or {}) do
mt_new[k] = v
end
for k, v in _G.pairs(el) do
t[k] = v
end
end
end
mt_new = concat(mt_old, mt_new)
mt_new.__index = mt_new
t.__parent = mt_new
_G.setmetatable(t, mt_new)
return t
end
return t
end
Объявляем классы
Код
A = class{
f1 = function()
Core.SendToAll"A.f1"
end;
}
B = A{
f1 = function()
Core.SendToAll"B.f1"
end;
f2 = function()
Core.SendToAll"B.f2"
end;
}
C = class{
f2 = function()
Core.SendToAll"C.f2"
end;
f3 = function()
Core.SendToAll"C.f3"
end;
}
D = B{
f1 = function()
Core.SendToAll"D.f1"
end;
f2 = function()
Core.SendToAll"D.f2"
end;
f3 = function()
Core.SendToAll"D.f3"
end;
}
D = C(D) -- реализация множественного наследования
Структура наследования такова:
* класс A - базовый класс
* класс B - наследует класс A
* класс С - базовый класс
* класс D - наследует классы B и С (множественное наследование)
Вызов функций классов:
Код
Core.SendToAll"\t\tВызываем в каждом классе свои функции:"
Core.SendToAll"\tКласс A"
A.f1()
Core.SendToAll"\tКласс B"
B.f1()
B.f2()
Core.SendToAll"\tКласс C"
C.f2()
C.f3()
Core.SendToAll"\tКласс D"
D.f3()
D.f3()
D.f3()
Core.SendToAll"\t\tВызываем в классе D унаследованные функции:"
D.__parent.__parent.f1()
D.__parent.f1()
D.__parent.f2()
D.__parent.f3()
Что выводится на экран:
Цитата
Вызываем в каждом классе свои функции:
Класс A
A.f1
Класс B
B.f1
B.f2
Класс C
C.f2
C.f3
Класс D
D.f3
D.f3
D.f3
Вызываем в классе D унаследованные функции:
A.f1
B.f1
B.f2
C.f3
Автор: Wariner 8.3.2009, 13:53
чем больше пытаюсь разобраться тем больше путаюсь. предположительный ответ
Цитата
first_class_mMember2
2
Setuper: Илюх если ответ не правильный то напиши что неправильно я буду пробовать дальше сам(ответ не пиши)!!!
Автор: Setuper 8.3.2009, 14:32
Неправильный
Вот пример для проверки
Код
cMyFirstClass = cClass{
mMember1 = 5;
mMember2 = "first_class_mMember2";
func1 = function(self)
Core.SendToAll(self.mMember2)
end
func2 = function(self)
Core.SendToAll"Example"
end
}
cMySecondClass = cMyFirstClass{
mMember2 = "second_class_mMember2";
func3 = function(self)
self:func2()
end
}
cMySecondClass:func1()
Просто нужно понять что такое наследование.
Автор: Setuper 9.4.2009, 12:12
Описание класса с функциями "необязательного объявления".
Суть функций "необязательного объявления": при модульном написании проектов, иногда существует потребность в отключении некоторых функций. Эта потребность связана с варьированием функционала проекта в зависимости от потребностей пользователей.
Предлагаемое описание класса позволяет даже не загружать модули с объявлениями функций, но тем не менее использовать вызовы этих функций. Не объявленные функции будут выполняться как функции-заглушки, то есть не будут ничего делать и будут возвращать значение nil.
На этапе отладки работы с модулями рекомендуется создать функцию логирования загрузок всех модулей, дабы понять какой модуль не был загружен, и следовательно функции какого модуля были заменены на функции-заглушки.
Код
--[[
*
* Copyright (C) 2009 by Setuper
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
]]
--[[ Module for building of classes with inheritance
* Returns function for building of the class
*
* class(...)
*
* @author Setuper
]]
do
local _G = _G
local function concat(p1, p2)
local t = {}
for k, v in _G.pairs(p1) do
t[k] = v
end
for k, v in _G.pairs(p2) do
t[k] = v
end
if _G.next(p1.__parent or {}) or _G.next(p2.__parent or {}) then
t.__parent = concat(p1.__parent or {}, p2.__parent or {})
end
return t
end
class = function(...)
local t, m = {}, {}
_G.setmetatable(t, m)
for i = 1, _G.select('#', ...) do
local p = _G.select(i, ...)
if _G.type(p) == "table" then
for k, v in _G.pairs(p) do
t[k] = v
end
end
end
m.__call = function(self, ...)
local t, mt_old, mt_new = {}, {}, {}
for k, v in _G.pairs(_G.getmetatable(self) or {}) do
mt_old[k] = v
end
for k, v in _G.pairs(self) do
mt_old[k] = v
end
for i = 1, _G.select('#', ...) do
local p = _G.select(i, ...)
if _G.type(p) == "table" then
for k, v in _G.pairs(_G.getmetatable(p) or {}) do
mt_new[k] = v
end
for k, v in _G.pairs(p) do
t[k] = v
end
end
end
mt_new = concat(mt_old, mt_new)
mt_new.__index = function(self, key)
if t.__parent[key] then
return t.__parent[key]
else
return function(self)
return nil
end
end
end
t.__parent = mt_new
_G.setmetatable(t, mt_new)
return t
end
return t
end
end
Автор: Setuper 3.5.2009, 18:20
Простой пример скрипта RegCmd на использование классов.
Содержит наглядные примеры использования в lua:
- классов
- объектов
- модулей
- передачи параметров по ссылке и по значению
- инкапсуляции
Не содержит наглядных примеров на использование аппаратов наследования и полиморфизма (рассмотрено ранее).
example.rar ( 4.53 килобайт )
: 45