Lua从入门到入了门(3) OOP深入分析之教科书版

原始实现

源代码地址http://www.lua.org/pil/16.2.html

我做了些许改变,代码如下:

Account.lua文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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
print("你没那么多钱 取不出来的 兄弟")
return
end
self.balance = self.balance - v
end

SpecialAccount.lua文件

1
2
3
4
5
6
7
8
9
10
11
12
SpecialAccount = Account:new()

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

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

入口文件

1
2
3
4
5
6
7
8
9
10
11
12
require("Account")
require("SpecialAccount")

normalAccount = Account:new()
normalAccount:deposit(100.00)
normalAccount:withdraw(300)
print("普通账户当前存款: "..normalAccount.balance)

sAccount = SpecialAccount:new{limit = 1000.00}
sAccount:deposit(100.00)
sAccount:withdraw(300)
print("特殊账户当前存款: "..sAccount.balance)

输出结果:

1
2
3
4
你没那么多钱 取不出来的 兄弟
普通账户当前存款: 100.0

特殊账户当前存款: -200.0

分析

OOP核心部分实现代码就是这块:

1
2
3
4
5
6
7
8
9
10
function Account:new (o)
o = o or {}
setmetatable(o, self)
self.__index = self
return o
end

--外部调用方法

normalAccount = Account:new()

直接去除语法糖,更换变量名 将上面代码 等效 转化为 如下代码:

1
2
3
4
5
6
7
8
9
10
11
12

Account.new = function (_firstArg, _newTable)
_newTable = _newTable or {}
setmetatable(_newTable, _firstArg)
_firstArg.__index = _firstArg
return _newTable
end


--外部调用方法

normalAccount = Account.new(Account)

如果你对为何能等效转换及2B情景法有疑问,请看我之前的文章: Lua从入门到入了门(2) 基础难点概述

然后让我用2B情景法翻译一下上面那段

_newTable就是小弟,_firstArg也就是调用时候传入的Account就是大哥

setmetatable(_newTable, _firstArg) 让小弟认了大哥

_firstArg.__index = _firstArg 大哥偷懒,直接将查找函数指向了自己,(参考之前例子中GreenPaper)

然后直接return 了小弟, 小弟就可以自己去愉快的玩耍了.

小结

教科书给出的OOP模拟方式是最好理解的,但是相应的会在编写上稍显复杂. 比如 SpecialAccount声明时候要去写 SpecialAccount = Account:new()

所以这个例子更多的是教学意义大于实际意义

坚持原创技术分享,您的支持将鼓励我继续创作!