Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

MyDC.ru _ Программирование на Lua _ ООП в Lua. Использование замыканий.

Автор: 96username96 15.11.2012, 13:39

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

Меня, как и многих других, интересуют технологии объектно-ориентированного программирования в 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()


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

Автор: tolven 23.4.2013, 15:36

Похоже на си код. Спасибо сохраним.
http://mydc.ru/r/?http://reducingflange.ruhttp://mydc.ru/r/?http://sagprofile.ruhttp://mydc.ru/r/?http://magnetotelluricfield.ruhttp://mydc.ru/r/?http://seawaterpump.ruhttp://mydc.ru/r/?http://recordedassignment.ruhttp://mydc.ru/r/?http://telangiectaticlipoma.ruhttp://mydc.ru/r/?http://oceanmining.ruhttp://mydc.ru/r/?http://neighbouringrights.ruhttp://mydc.ru/r/?http://leadingfirm.ruhttp://mydc.ru/r/?http://qualitybooster.ruhttp://mydc.ru/r/?http://randomcoloration.ruhttp://mydc.ru/r/?http://railwaybridge.ruhttp://mydc.ru/r/?http://radiationestimator.ruhttp://mydc.ru/r/?http://tailstockcenter.ruhttp://mydc.ru/r/?http://referenceantigen.ruhttp://mydc.ru/r/?http://quasimoney.ruhttp://mydc.ru/r/?http://regeneratedprotein.ruhttp://mydc.ru/r/?http://necroticcaries.ruhttp://mydc.ru/r/?http://navelseed.ruhttp://mydc.ru/r/?http://negativefibration.ruhttp://mydc.ru/r/?http://octupolephonon.ruhttp://mydc.ru/r/?http://offlinesystem.ruhttp://mydc.ru/r/?http://offsetholder.ruhttp://mydc.ru/r/?http://onesticket.ruhttp://mydc.ru/r/?http://obstructivepatent.ruhttp://mydc.ru/r/?http://laterevent.ruhttp://mydc.ru/r/?http://learningcurve.ruhttp://mydc.ru/r/?http://leaveword.ruhttp://mydc.ru/r/?http://mammasdarling.ruhttp://mydc.ru/r/?http://rattlesnakemaster.ruhttp://mydc.ru/r/?http://rearchain.ruhttp://mydc.ru/r/?http://redemptionvalue.ruhttp://mydc.ru/r/?http://safedrilling.ruhttp://mydc.ru/r/?http://samplinginterval.ruhttp://mydc.ru/r/?http://satellitehydrology.ruhttp://mydc.ru/r/?http://scrapermat.ruhttp://mydc.ru/r/?http://screwingunit.ruhttp://mydc.ru/r/?http://secondaryblock.ruhttp://mydc.ru/r/?http://semiasphalticflux.ruhttp://mydc.ru/r/?http://semifinishmachining.ruhttp://mydc.ru/r/?http://telescopicdamper.ruhttp://mydc.ru/r/?http://ultramaficrock.ruhttp://mydc.ru/r/?http://ultraviolettesting.ruhttp://mydc.ru/r/?http://reachthroughregion.ruhttp://mydc.ru/r/?http://readingmagnifier.ruhttp://mydc.ru/r/?http://recessioncone.ruhttp://mydc.ru/r/?http://reinvestmentplan.ruhttp://mydc.ru/r/?http://salestypelease.ruhttp://mydc.ru/r/?http://scarcecommodity.ruhttp://mydc.ru/r/?http://secularclergy.ru