lyh916

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

这里主要说一下Lua在面向对象的使用中需要注意的地方。

 

一.self

self指的是调用者自身,例如:

local a = Shape:New(nil, 10),即local a = Shape.New(self, nil, 10),self指的是Shape;

a:PrintArea(),即a.PrintArea(self),self指的是a。

 1 Shape = {area = 0}
 2 
 3 function Shape:New(o, side)
 4     o = o or {}
 5     setmetatable(o, self)
 6     self.__index = self
 7     side = side or 0
 8     self.area = side * side
 9     return o
10 end
11 
12 function Shape:PrintArea()
13     print("面积为 ", self.area)
14 end
15 
16 print(Shape.area)
17 
18 local a = Shape:New(nil, 10)
19 a:PrintArea()
20 print(Shape.area)
21 
22 local b = Shape:New(nil, 20)
23 b:PrintArea()
24 print(Shape.area)
25 
26 a:PrintArea()
27 print(Shape.area)

输出分析:

第二句,在Shape:New(nil, 10)时,Shape.area被赋值为100,在a:PrintArea()时,本来要打印的是a.area,但该键值为空,实际打印的是Shape.area。

第六句,在Shape:New(nil, 20)时,Shape.area被赋值为400。

 

那么,可以将上面的self.area = side * side改一下,改为o.area = side * side,输出如下。可以看到,此时New出来的实例都有各自的area值,不影响Shape表,此时才是符合面向对象设计的。

 

二.元表的__index元方法

__index元方法是用来查找值的,因此可以认为是“可读不可写”的。当查找到表中的某键的值为nil时,就会访问元表的__index元方法。

如下输出所示,可以发现:

1.像a.xxx这种,都是直接对a表进行赋值,不影响Shape表;而a.testTb[2]这种非直接赋值,会影响Shape表

 1 Shape = {area = 0, test = 123, testTb = {"q","w"}}
 2 
 3 function Shape:New(o, side)
 4     o = o or {}
 5     setmetatable(o, self)
 6     self.__index = self
 7     side = side or 0
 8     --self.area = side * side
 9     o.area = side * side
10     return o
11 end
12 
13 function Shape:PrintArea()
14     print("面积为 ", self.area)
15 end
16 
17 local a = Shape:New(nil, 10)
18 print(a.test)
19 print(a.test2)
20 print(Shape.test)
21 
22 print("------------------------")
23 a.test = 456
24 print(a.test)
25 print(Shape.test)
26 
27 print("------------------------")
28 Shape.test = 789
29 print(a.test)
30 print(Shape.test)
31 
32 print("------------------------1")
33 print(a.testTb[2])
34 a.testTb[2] = "z"
35 
36 print("------------------------2")
37 a.testTb = nil
38 for i=1,#a.testTb do
39     print(a.testTb[i])
40 end
41 print("------------------------3")
42 for i=1,#Shape.testTb do
43     print(Shape.testTb[i])
44 end
45 
46 print("------------------------4")
47 a.testTb = {}
48 for i=1,#a.testTb do
49     print(a.testTb[i])
50 end
51 print("------------------------5")
52 for i=1,#Shape.testTb do
53     print(Shape.testTb[i])
54 end

 

三.默认值

1.使用元表设置默认值,这种方法的好处是修改元表后,会修改所有子表的默认值。

 1 Shape = {area = 0, test = 123}
 2 
 3 function Shape:New(o, side)
 4     o = o or {}
 5     setmetatable(o, self)
 6     self.__index = self
 7     side = side or 0
 8     --self.area = side * side
 9     o.area = side * side
10     return o
11 end
12 
13 function Shape:PrintArea()
14     print("面积为 ", self.area)
15 end
16 
17 local a = Shape:New(nil, 10)
18 local b = Shape:New(nil, 10)
19 print(a.test)
20 print(b.test)
21 print(Shape.test)
22 Shape.test = 456
23 print(a.test)
24 print(b.test)

 

2.使用New设置默认值,这种方法会使每张表有各自的值,修改元表不会对其进行影响。

 1 Shape = {area = 0, test = 123}
 2 
 3 function Shape:New(o, side)
 4     o = o or {}
 5     setmetatable(o, self)
 6     self.__index = self
 7     side = side or 0
 8     --self.area = side * side
 9     o.area = side * side
10     o.test = 789
11     return o
12 end
13 
14 function Shape:PrintArea()
15     print("面积为 ", self.area)
16 end
17 
18 local a = Shape:New(nil, 10)
19 local b = Shape:New(nil, 10)
20 print(a.test)
21 print(b.test)
22 print(Shape.test)
23 Shape.test = 456
24 a.test = 111
25 print(a.test)
26 print(b.test)

 

四.调用父类方法

 1 Shape = {}
 2 
 3 function Shape:New(o, side)
 4     o = o or {}
 5     setmetatable(o, self)
 6     self.__index = self
 7     side = side or 0
 8     o.area = side * side
 9     return o
10 end
11 
12 function Shape:PrintArea()
13     print("Shape面积为 ", self.area)
14 end
15 
16 Square = Shape:New()
17 
18 function Square:New(o, side)
19     o = o or {}
20     setmetatable(o, self)
21     self.__index = self
22     side = side or 0
23     o.area = side * side
24     return o
25 end
26 
27 function Square:PrintArea()
28     print("Square面积为 ", self.area)
29     Shape.PrintArea(self)
30 end
31 
32 local a = Shape:New(nil, 10)
33 local b = Square:New(nil, 20)
34 print(a:PrintArea())
35 print("-------------")
36 print(b:PrintArea())

 

五.继承中的table问题

 1 A = {}
 2 
 3 function A:New()
 4     local o = {}
 5     setmetatable(o, self)
 6     self.__index = self
 7     o.child = {}
 8     return o
 9 end
10 
11 function A:AddChild()
12     table.insert(self.child, 1)
13 end
14 
15 function A:Print()
16     print(#self.child)
17 end
18 
19 B = A:New()
20 
21 function B:New()
22     local o = {}
23     setmetatable(o, self)
24     self.__index = self
25     return o
26 end
27 
28 local b1 = B:New();
29 local b2 = B:New();
30 b1:AddChild()
31 b1:Print()
32 b2:Print()
33 b2:AddChild()
34 b2:Print()

如上,b1和b2共用A表中的child,而正确来说b1和b2要有各自的child,因此在B:New()中添加语句:o.child = {},输出如下:

 

posted on 2018-08-30 23:19  艰苦奋斗中  阅读(384)  评论(0编辑  收藏  举报