-
Notifications
You must be signed in to change notification settings - Fork 21
/
Copy pathchapter21.lua
164 lines (141 loc) · 4.32 KB
/
chapter21.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
---练习21.1 实现一个类Stack,该类具有push、pop、top、isempty
local stack = {}
stack.__index = stack
function stack:new(o)
o = o or {}
setmetatable(o,self)
o.list = {}
return o
end
function stack:isempty()
return #self.list == 0
end
function stack:push(v)
assert(v,"push data is nil")
self.list[#self.list + 1] = v
end
function stack:top()
if self:isempty() then error("cannot get top,stack is empty") end
return self.list[#self.list]
end
function stack:pop()
if self:isempty() then error("pop error,stack is empty") end
local v = self.list[#self.list]
table.remove(self.list)
return v
end
--local stk = stack:new()
--local stk2 = stack:new()
--stk:push(1)
--stk:push(2)
--stk:push(3)
--print(stk:top())
--print(stk:pop())
--print(stk:top())
--print(stk:isempty())
--print(stk2:isempty())
---练习21.2 实现类Stack的子类StackQueue。除了继承的方法外,还给这个子类增加一个方法insertbottom。
---该方法在栈的底部插入一个元素(这个方法使得我们可以把这个类的实例当作队列)
local StackQueue = stack:new()
StackQueue.__index = StackQueue
function StackQueue:insertbottom(v)
assert(v,"insert value is nil")
table.insert(self.list,1,v)
end
--local stkqueue = StackQueue:new()
--stkqueue:push(1)
--stkqueue:insertbottom(2)
--stkqueue:insertbottom(3)
--print(stkqueue:pop())
--print(stkqueue:pop())
--print(stkqueue:pop())
---练习21.3 使用对偶表示重新实现类Stack
local DualStack = {}
local stackContainer = {}
DualStack.__index = DualStack
function DualStack:new(o)
o = o or {}
setmetatable(o,self)
stackContainer[o] = {}
return o
end
function DualStack:isempty()
return #stackContainer[self] == 0
end
function DualStack:push(v)
assert(v,"push data is nil")
table.insert(stackContainer[self],v)
end
function DualStack:top()
if self:isempty() then error("cannot get top,stack is empty") end
return stackContainer[self][#stackContainer[self]]
end
function DualStack:pop()
if self:isempty() then error("pop error,stack is empty") end
local v = stackContainer[self][#stackContainer[self]]
table.remove(stackContainer[self])
return v
end
--local stk3 = DualStack:new()
--local stk4 = DualStack:new()
--stk3:push(1)
--stk3:push(2)
--stk3:push(3)
--print(stk3:top())
--print(stk3:pop())
--print(stk3:top())
--print(stk3:isempty())
--print(stk4:isempty())
---练习21.4 对偶表示的一种变形是使用代理表示对象(20.4.4节)。每一个对象由一个空的代理表表示。
---一个内部的表把代理映射到保存对象状态的表。这个内部表不能从外部访问,但是方法可以使用内部表来把self变量转换为要操作的表。
---请使用这种方式实现银行账户的示例,然后讨论这种方式的优点和缺点。
--优点 很好的将数据进行了封装 避免从外部直接访问修改
--缺点 由于返回的是proxy空表,因此调试的适合不方便获取类的内部信。 此外由于内部代理表的存在,对象使用过后无法被垃圾回收。
do
local Account = {}
local proxies = {}
local mt = {
__index = function(t,k)
local objstate = proxies[t]
if objstate then
if type(objstate[k]) ~= "function"then error("try to access object's private data,key:" .. tostring(k)) end
return objstate[k]
end
end
}
function Account:withdraw(v)
self.balance = self.balance - v
end
function Account:deposit(v)
self.balance = self.balance + v
end
function Account:getBalance()
return self.balance
end
function Account:new(o)
o = o or {balance = 0}
self.__index = self
setmetatable(o,self)
return o
end
function account_proxy()
local obj = Account:new()
local proxy = {}
proxies[proxy] = obj
setmetatable(proxy,mt)
return proxy
end
end
--local account1 = account_proxy()
--local account2 = account_proxy()
--print(account1:getBalance())
--account1:withdraw(2)
--print(account1:getBalance())
--account1:deposit(10)
--print(account1:getBalance())
--print("--------------------")
--print(account2:getBalance())
--account2:withdraw(5)
--print(account2:getBalance())
--account2:deposit(6)
--print(account2:getBalance())