Lua面向对象

Lua中的表就是一个对象.表与对象一样,可以拥有状态.拥有一个与其值无关的标识(self) 两个具有相同值的对象(表)是两个不同的对象,而一个对象可以具有多个不同的值.表与对象一样,具有与创建者和被创建者位置无关的生命周期.

Account = {balance = 0} -- 使用表模拟类,并设置属性balance的值为零

function Account.withdraw(n) -- 定义行为
    Account.balance = Account.balance - v
end

Account.withdraw(12.01) --

Note: 上述代码中withdraw方法只能针对特定对象工作.这个方法只有在对象保存在特定的全局变量中才能工作,如果我们改变了对象的名称,withdraw就不能工作了.这种行为违反了对象拥有独立生命周期的原则.

a, Account = Account, nil
a.withdraw(10.0) -- Error!

如果想要解决上述的那种情况,可以对操作的接受者进行操作.这是需要一个额外的参数来表示该接受者,这个参数通常被称为self或this

function Account.withdraw(self, n)
    self.balance = self.balance - n
end

a = Account; Account = nil
a.withdraw(10) -- success!

使用self参数是所有面向对象语言的核心点.大多数面向对象语言都向程序员隐藏了这个机制,从而使得程序员不必显示地声明这个参数. 同样的我们还可以使用冒号(:)操作符来隐藏该参数.冒号的作用是在一个方法调用中增加一个额外的实参,或在方法的定义中增加一个额外的隐藏参数. 冒号只是一种语法机制,并没有引入任何新的东西.

Account = {balance = 0, 
    withdraw = function(self, n)
                    self.balance = self.balance - n
               end
}

function Account:deposit(value)
    self.balance = self.balance + value
end

Account.deposit(10)
Account:withdraw(10)

Lua语言中没有类的概念.虽然元表的概念在某种程度上与类的概念相似,但是把元表当作类使用在后续会比较麻烦 相对的,Lua可以采用原型的模式来模拟.即每个对象都可以有一个原型.原型也是一种普通对象,当对象遇到一个未知的操作时会首先在原型中查找.

function Account:new(o)
    o = o or {}
    self.__index = self
    setmetatable(o, self)
    return o
end
继承

由于类也是对象,因此它们也可以从其他类获得方法.(通过原型来查找)

Account = {balance = 0}

function Account:new(o)
    o = o or {}
    self.__index = self
    setmetatable(o, self)
    return o
end

function Account:deposit(value)
    if value > self.balance then
        error "insufficent funds!!!"
    end
    self.balance = self.balance - value
end

function Account:withdraw(value)
    if value > self.balance then
        error "insufficent funds!!!"
    end
    self.balance = self.balance + value
end

SpecicalAccount = Account:new() -- SpecicalAccount继承了Account

s = SpecicalAccount:new{limit=100.10} -- 这重新调用new时,self指向的是SpecicalAccount

-- s的元表是SpecicalAccount,其中字段__index的值也是SpecicalAccount.因此,s继承自SpecicalAccount,而SpecicalAccount继承自Account

function SpecicalAccount:withdraw(value) -- 重新定义从基类继承的(任意)方法
    if value - self.balance > self:getLimit() then
        error "insufficent funds!!!"
    end
    self.balance = self.balance - v
end

function SpecicalAccount:getLimit()
    return self.limit or 0
end

Note: 在lua中的对象有个比较有趣的特性,就是无须为了指定一种新行为而创建一个新的类.如果只有单个对象需要某中特殊行为,那么我们可以直接在该对象中实现该行为.

function s:getLimit()
    return self.balance * 0.01
end

that's all

results matching ""

    No results matching ""