Lua面向对象编程

本文深入探讨了Lua语言中面向对象编程的实现方法,包括如何使用元表和元方法实现继承,以及如何通过冒号语法定义和调用成员函数。通过具体的代码示例,展示了如何创建和使用具有存款和取款功能的Account类,并进一步扩展为具有透支能力的SpecialAccount类。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Account = {balance = 0}

function Account.withdraw(v)
    Account.balance = Account.balance - v
end

Account.withdraw(100)

print(Account.balance)

------------------------------------------------------------------------------------------------

--[[
在函数中使用全局名称是一个不好的编程习惯。
因为这个函数只能针对特对象工作,并且,这个特定对象还必须存储在特定的全局变量中。
--]]

-- a = Account Account = nil  --> 因为函数withdraw(v)中使用了Account.balance,此时Account = nil
-- a.withdraw(100)


-- 当改成如下,withdraw中去掉Account.balance,调用正常
function Account.withdraw(v)
    print "1"
end

a = Account Account = nil
a.withdraw(100)


------------------------------------------------------------------------------------------------
Account = {balance = 0}

-- 解决方案:
-- 指定一项操作所作用的“接受者”。
-- 需要一个额外的参数来表示该接受者。
-- 这个参数通常称为self或this

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

a1 = Account Account = nil
a1.withdraw(a1, 100)


------------------------------------------------------------------------------------------------
Account = {balance = 0}

-- Lua只需使用冒号,则能隐藏该参数self。只是一种语法便利,并没有引入任何新的东西。
--重写:function Account.withdraw(self, v)
function Account:withdraw(v)
    self.balance = self.balance - v
end


------------------------------------------------------------------------------------------------

-- 用点语法来定义一个函数,并用冒号语法调用它。
Account = {
    balance = 0,
    withdraw = function (self, v)           -- 1. 点语法定义
        self.balance = self.balance - v
    end
}

function Account:deposit(v)                 -- 2. 冒号语法定义
    self.balance = self.balance + v
end

Account:withdraw(100.00)                    -- 1. 冒号语法调用

Account.deposit(Account, 200)               -- 2. 点语法调用
Account:deposit(200)                        -- 2. 冒号语法调用

------------------------------------------------------------------------------------------------

--[[
类
--]]

-- example
-- 1. 检查该table中是否有这个key,若无
-- 2. 检查该table是否设置过metatable,若有
-- 3. 检查metatable中是否有__index,若有
-- 4. 检查__index下是否有这个key,若有
-- 5. 返回getmetatable(x).__index.key
local kid = {}
local father = {property = 11}
setmetatable(kid, father)       -- 设置元表,仅仅设置元表并不能使lua寻找父类的方法或属性
father.__index = father         -- 设置元方法(注意是设置父!)
father.anotherProperty = 22     -- 给fahter表增加一个属性
kid.money = 33                  -- 给kid表增加一个属性
print(kid.property)             -- 11, 返回父类father中property的值
print(kid.anotherProperty)      -- 22,父类增加的属性和方法都可以被子类继承
print(father.money)             -- nil,相反,父类并不可以获取子类的值



-- 创建更多与Account行为类似的账号(实例化)
-- 具体做法就是使用__index元方法 setmetatable(a, {__index = b})

function Account:new(o)
    o = o or {}         -- 如果用户没有提供table,则创建一个
    setmetatable(o, self)
    self.__index = self
    return o
end


yqbAccount = Account:new{balance = 0}
yqbAccount:deposit(999.00)

print("balance of yqbAccount: ", yqbAccount.balance)


------------------------------------------------------------------------------------------------

--[[
继承
--]]

Account = {balance = 0}

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

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

function Account:withdraw(v)
    if v > self.balance then
        error "insufficient funds"
    end
    self.balance = self.balance - v
end

-- 想派生可以透支的SpecialAccount

-- 创建一个空的类,继承了Account的所有方法(包括new)和属性
SpecialAccount = Account:new()
-- 实例化一个SpecialAccount,这次执行new时,它的self参数表示为SpecialAccount
s = SpecialAccount.new{limit = 1000.00}

function SpecialAccount:getLimit()
    return self.limit or 0
end
-- 重写
function SpecialAccount:withdraw(v)
    if v - self.balance >= self.getLimit() then     -- 超过了透支值,不给透支
        error "insufficient funds"
    end
    self.balance = self.balance - v
end


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值