myDC.ru

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

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

> ООП в Lua. Использование замыканий.

Теги
Нет тегов для показа
96username96
сообщение 15.11.2012, 13:39
Сообщение #1


Абсолютный новичок


Группа: Пользователи
Сообщений: 1
Регистрация: 29.10.2012
Из: Екатеринбург
Пользователь №: 10 983
Спасибо сказали: 2 раза




Здравствуйте, уважаемое Сообщество

Меня, как и многих других, интересуют технологии объектно-ориентированного программирования в Lua.
Из литературы по Lua известен следующий пример:

Раскрывающийся текст
Код
function anyClass(value)

    local function get()
        return value
    end
    
    local function set(v)
        value = v
    end
    
    return { get = get, set = set }
end

local x = anyClass(123)
print( x.get() )
x.set(987)
print( x.get() )

Данная технология программирования интересна тем, что позволяет использовать private-переменные при помощи механизма замыканий.
Все описания данного приёма программирования, которые я встретил, ограничиваются вышеописанным примером.
Способы организации наследования классов мне нигде не попадались. Поэтому хочется поделиться своими.

Далее будет довольно большой пример.

Раскрывающийся текст
Код
local print = print

local function Object()
    local PUBLIC  = {} -- public, interface
    local VIRTUAL = {} -- protected, virtual
    return PUBLIC, VIRTUAL
end

local function Figure()
    -- inheritance
    local PUBLIC, VIRTUAL = Object()
    local this = VIRTUAL
    
    -- private
    local function CreateDC()
        print 'Create DC'
    end
    
    local function ReleaseDC()
        print 'Release DC\n'
    end
    
    local function BeginPaint()
        print 'Begin Paint'
    end
    
    local function EndPaint()
        print 'End Paint'
    end
    
    function PUBLIC.Draw() -- public method
        CreateDC()
        BeginPaint()
        VIRTUAL.Draw() -- virtual call
        EndPaint()
        ReleaseDC()
    end
    
    VIRTUAL.Draw = nil -- abstract method
    
    return PUBLIC, VIRTUAL
end

local function Point(x, y)
    local PUBLIC, VIRTUAL = Figure()
    local this = VIRTUAL
    
    function PUBLIC.Set(x, y)
        this.x = x + 0
        this.y = y + 0
    end
    
    PUBLIC.Set(x, y) -- initialization
    
    function PUBLIC.Get()
        return this.x, this.y
    end
        
    function VIRTUAL.Draw()
        print( '\tDraw Point', this.x, this.y )
    end
    
    return PUBLIC, VIRTUAL
end

local function Text(x, y, txt)
    local PUBLIC, VIRTUAL = Point(x, y)
    local this = VIRTUAL
    local SUPER = { Set = PUBLIC.Set, Get = PUBLIC.Get }
    
    function PUBLIC.Set(x, y, txt)
        SUPER.Set(x, y)
        this.txt = txt .. ''
    end
    
    PUBLIC.Set(x, y, txt)
    
    function PUBLIC.Get()
        return this.x, this.y, this.txt
    end
    
    function VIRTUAL.Draw()
        print( '\tDraw Text', this.x, this.y, this.txt )
    end
    
    return PUBLIC, VIRTUAL
end

local function Rect(x, y, w, h)
    local PUBLIC, VIRTUAL = Point(x, y)
    local this = VIRTUAL
    local SUPER = { Set = PUBLIC.Set, Get = PUBLIC.Get }
    
    function PUBLIC.Set(x, y, w, h)
        SUPER.Set(x, y)
        this.w = w + 0
        this.h = h + 0
    end
    
    PUBLIC.Set(x, y, w, h)
    
    function PUBLIC.Get()
        return this.x, this.y, this.w, this.h
    end
    
    VIRTUAL.Draw = nil
    
    return PUBLIC, VIRTUAL
end

local function Rectangle(x, y, w, h)
    local PUBLIC, VIRTUAL = Rect(x, y, w, h)
    local this = VIRTUAL
    
    function VIRTUAL.Draw()
        print( '\tDraw Rectangle', this.x, this.y, this.w, this.h )
    end
    
    -- define operator
    function PUBLIC.__tostring()
        return ("{ Rectangle %d, %d, %d, %d }"):format(this.x, this.y, this.w, this.h)
    end
    setmetatable(PUBLIC, PUBLIC)
    
    return PUBLIC, VIRTUAL
end

local function Ellipse(x, y, w, h)
    local PUBLIC, VIRTUAL = Rect(x, y, w, h)
    local this = VIRTUAL
    
    function VIRTUAL.Draw()
        print( '\tDraw Ellipse', this.x, this.y, this.w, this.h )
    end
    
    function VIRTUAL.__tostring()
        return ("{ Ellipse %d, %d, %d, %d }"):format(this.x, this.y, this.w, this.h)
    end
    setmetatable(PUBLIC, VIRTUAL)
    
    return PUBLIC, VIRTUAL
end


local point1 = Point(5, 99)
local point2 = Point(333, 7)

point1.Draw()
point2.Draw()
point1.Draw()

local rect1 = Rectangle(2, 5, 20, 30)
rect1.Draw()

local rect2 = Rectangle(100, 100, 100, 100)
rect2.Draw()
rect1.Draw()
rect1.Set(1, 1, 1, 1)
rect1.Draw()
print(rect1, '\n')
print(rect1.__tostring(), '\n')

local ell1 = Ellipse(33, 44, 55, 66)
ell1.Draw()
print( ell1, '\n' )

local text1 = Text(400, 200, 'Aaaaaaaaaaaaaaaaaaaaaa')
local text2 = Text(4, 5, 'Bbbbbbbbbbbbbbbbbbbbbb')
text1.Draw()
text2.Draw()
text2.Set(333, 333, '**********************')
text2.Draw()


Как видно из примера, при помощи замыканий можно создавать нечто очень близкое к классическому ООП.
В следующем примере показано создание внутреннего класса, как именованного, так и анонимного.
Оба класса имеют доступ к полям и методам содержащего их класса. Прямо Java big_smile.gif.

Раскрывающийся текст
Код
function Object()
    local PUBLIC  = {}
    local VIRTUAL = {}
    return PUBLIC, VIRTUAL
end

function Iterator()local PUBLIC,VIRTUAL=Object()
    
    function PUBLIC.Iterate()
        VIRTUAL.First()
        while VIRTUAL.Next() do
            VIRTUAL.Exec()
        end
    end
    
return PUBLIC,VIRTUAL end

-- Пример с обычным классом-наследником
function MyIterator()local PUBLIC,VIRTUAL=Iterator()
    
    local array = { 2, 4, 3, 9, 6 }
    local pos = 0;
    
    function VIRTUAL.First()
        pos = 0
    end
    
    function VIRTUAL.Next()
        pos = pos + 1
        return pos <= #array
    end
    
    function VIRTUAL.Exec()
        print(pos, array[pos])
    end
    
return PUBLIC,VIRTUAL end

--[[
local iter = MyIterator()
iter.Iterate()
--]]

-- Пример с внутренними классами
function Test()local PUBLIC,VIRTUAL=Object()
    
    local array = { 89, 32.74, 892, 64.000001, 3488, 9, 589, 534 }
    local pos = 0
    -- Внутренний класс
    local function Iterator1()local PUBLIC,VIRTUAL=Iterator()
        
        function VIRTUAL.First()
            pos = 0
        end
        
        function VIRTUAL.Next()
            pos = pos + 1
            return pos <= #array
        end
        
        function VIRTUAL.Exec()
            print('Test1', pos, array[pos])
        end
        
    return PUBLIC,VIRTUAL end
    
    function PUBLIC.Test1()
        print '{1}'
        local iter = Iterator1()
        iter.Iterate()
    end
    -- Анонимный внутренний класс
    do
        local object,class = Iterator()
        
        function class.First()
            pos = #array + 1
        end
        
        function class.Next()
            pos = pos - 1
            return pos >= 1
        end
        
        function class.Exec()
            print('Test2', pos, array[pos])
        end
        
        function PUBLIC.Test2()
            print '{2}'
            object.Iterate()
        end
    end
    --
return PUBLIC,VIRTUAL end

local test = Test()
test.Test1()
test.Test2()


Буду рад, если вышеописанное кому-нибудь пригодится.


Спасибо сказали:
Go to the top of the page
+Quote Post
tolven
сообщение 23.4.2013, 15:36
Сообщение #2


Абсолютный новичок


Группа: Пользователи
Сообщений: 1
Регистрация: 23.4.2013
Пользователь №: 11 474
Спасибо сказали: 0 раз




Похоже на си код. Спасибо сохраним.
..................................................
Go to the top of the page
+Quote Post

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

Collapse

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

  Тема Ответов Автор Просмотров Последнее сообщение
No New Posts От: ООП в Lua. Использование замыканий.
От темы с ID: 5362
0 Saymon21 1 764 15.11.2012, 14:08 Посл. сообщение: Saymon21
No New Posts Topic has attachments[RusHub] Использование posix capabilities
Linux ONLY
9 ShadoWx 5 381 1.2.2012, 22:46 Посл. сообщение: mariner
No New Posts Использование Прокси И Защита От Прокси...
"околопроксёвые" вопросы
0 dimetrius 4 082 15.7.2008, 19:16 Посл. сообщение: dimetrius

 



RSS Сейчас: 25.2.2018, 8:46