myDC.ru

Здравствуйте, гость ( Вход | Регистрация )

 
 
Ответить в данную темуНачать новую тему

> От: Объектно-ориентированные Принципы В Lua, От темы с ID: 1429

Теги
Нет тегов для показа
Setuper
сообщение 27.12.2008, 15:44
Сообщение #1


RusHub team lead
**************

Группа: Модераторы
Сообщений: 4 030
Регистрация: 20.6.2008
Из: г. Королёв (Моск. обл.)
Пользователь №: 46
Спасибо сказали: 1708 раз




Продолжаю знакомство с ООП в 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"..
"==============================================")


Спасибо сказали:
Go to the top of the page
+Quote Post
Setuper
сообщение 25.2.2009, 21:22
Сообщение #2


RusHub team lead
**************

Группа: Модераторы
Сообщений: 4 030
Регистрация: 20.6.2008
Из: г. Королёв (Моск. обл.)
Пользователь №: 46
Спасибо сказали: 1708 раз




Универсальная функция для создания класса в 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


Спасибо сказали:
Go to the top of the page
+Quote Post
Wariner
сообщение 8.3.2009, 13:53
Сообщение #3


Самый главный активист :-D
***********

Группа: Модераторы
Сообщений: 2 790
Регистрация: 29.6.2008
Из: г. Тула
Пользователь №: 97
Спасибо сказали: 440 раз




чем больше пытаюсь разобраться тем больше путаюсь. предположительный ответ
Цитата
first_class_mMember2

2Setuper: Илюх если ответ не правильный то напиши что неправильно я буду пробовать дальше сам(ответ не пиши)!!!
Go to the top of the page
+Quote Post
Setuper
сообщение 8.3.2009, 14:32
Сообщение #4


RusHub team lead
**************

Группа: Модераторы
Сообщений: 4 030
Регистрация: 20.6.2008
Из: г. Королёв (Моск. обл.)
Пользователь №: 46
Спасибо сказали: 1708 раз




Неправильный

Вот пример для проверки
Код
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()

Просто нужно понять что такое наследование.
Go to the top of the page
+Quote Post
Setuper
сообщение 9.4.2009, 12:12
Сообщение #5


RusHub team lead
**************

Группа: Модераторы
Сообщений: 4 030
Регистрация: 20.6.2008
Из: г. Королёв (Моск. обл.)
Пользователь №: 46
Спасибо сказали: 1708 раз




Описание класса с функциями "необязательного объявления".

Суть функций "необязательного объявления": при модульном написании проектов, иногда существует потребность в отключении некоторых функций. Эта потребность связана с варьированием функционала проекта в зависимости от потребностей пользователей.
Предлагаемое описание класса позволяет даже не загружать модули с объявлениями функций, но тем не менее использовать вызовы этих функций. Не объявленные функции будут выполняться как функции-заглушки, то есть не будут ничего делать и будут возвращать значение 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


Спасибо сказали:
Go to the top of the page
+Quote Post
Setuper
сообщение 3.5.2009, 18:20
Сообщение #6


RusHub team lead
**************

Группа: Модераторы
Сообщений: 4 030
Регистрация: 20.6.2008
Из: г. Королёв (Моск. обл.)
Пользователь №: 46
Спасибо сказали: 1708 раз




Простой пример скрипта RegCmd на использование классов.

Содержит наглядные примеры использования в lua:
  • классов
  • объектов
  • модулей
  • передачи параметров по ссылке и по значению
  • инкапсуляции


Не содержит наглядных примеров на использование аппаратов наследования и полиморфизма (рассмотрено ранее).


Прикрепленный файл  example.rar ( 4.53 килобайт ) Кол-во скачиваний: 45


Спасибо сказали:
Go to the top of the page
+Quote Post

Ответить в данную темуНачать новую тему
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

Collapse

> Похожие темы

  Тема Ответов Автор Просмотров Последнее сообщение
No New Posts Topic has attachmentsОбъектно-Ориентированное Программирование в Lua
Создание и использование классов
9 Setuper 32 841 1.7.2016, 9:24 Посл. сообщение: MIKHAIL

 



RSS Сейчас: 29.3.2024, 13:42