作爲一名lua新手,在使用騰訊xLua框架時,也是一邊在學習着Lua,對於點和冒號的用法一直理解的不夠透徹,找到了這篇文章,原文地址:
http://www.cnblogs.com/youxilua/archive/2011/07/28/2119059.html
首先,先來一段在lua創建一個類與對象的代碼
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
Class
= {} Class.__index
= Class function
Class:new(x,y) local
temp = {} setmetatable(temp,
Class) temp.x
= x temp.y
= y return temp end function
Class:test() print ( self .x, self .y) end object = Class.new( 10 , 20 ) object :test() |
猜一下會輸出什麼結果呢?
輸出:
>lua -e "io.stdout:setvbuf 'no'" "object.lua"
20 nil
>Exit code: 0
我們的y值怎麼沒了?
這個原因很簡單,因爲我們創建一個對象的時候使用了一個 . 號
在lua程序設計第二版中,有提到當一項操作所作用的”接受者”,需要一個額外的參數來表示該接受者,這個參數通常稱爲self或this
然後我們在這段代碼加上 self
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
Class
= {} Class.__index
= Class function
Class:new(x,y) local
temp = {} setmetatable(temp,
Class) temp.x
= x temp.y
= y return temp end function
Class:test() print ( self .x, self .y) end object = Class.new( self , 10 , 20 ) object :test() |
然後我們在看一下輸出
>lua -e "io.stdout:setvbuf 'no'" "object.lua"
10 20
>Exit code: 0
這下就正常了!!嗯,每次創建一個對象的時候都有寫一個self,會不會感覺很麻煩呢?lua提供了用冒號的方式在一個方法定義中添加一個額外的參數,以及在一個方法調用中添加一個額外的實參
然後代碼改成
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
Class
= {} Class.__index
= Class function
Class:new(x,y) local
temp = {} setmetatable(temp,
Class) temp.x
= x temp.y
= y return temp end function
Class:test() print ( self .x, self .y) end object = Class:new( 10 , 20 ) object :test() |
輸出正常:
>lua -e "io.stdout:setvbuf 'no'" "object.lua"
10 20
>Exit code: 0
如果,就這麼完的話,本來是一件很歡樂的事情,但是,我嘗試了一下以下代碼
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
Class
= {} Class.__index
= Class function
Class.new(x,y) local
temp = {} setmetatable(temp,
Class) temp.x
= x temp.y
= y return temp end function
Class:test() print ( self .x, self .y) end object = Class.new( 10 , 20 ) object :test() |
出乎意料的是:
>lua -e "io.stdout:setvbuf 'no'" "object.lua"
10 20
>Exit code: 0
代碼正常運行….這個讓人很費解,本來,點號對方法的操作是需要一個額外的接受者,第一段代碼已經說明了這個問題,但是,現在程序有正常運行,令我真是有點費解…
然後,我接着嘗試又發現
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
Class
= {} Class.__index
= Class function
Class.new(x,y) local
temp = {} setmetatable(temp,
Class) temp.x
= x temp.y
= y return temp end function
Class:test() print ( self .x, self .y) end object = Class:new( 10 , 20 ) object :test() |
輸出結果:
>lua -e "io.stdout:setvbuf 'no'" "object.lua"
table: 003CACA0 10
>Exit code: 0
這個只不過跟第一段代碼點號和冒號的位置調換了一下,就出現了這樣的結果…
如果,你仔細想想,這裏和第一段代碼的區別,可以發現,其實,這裏就可以證明了冒號其實就是默認傳了一個實參到方法中
爲了證明冒號的作用,我改動了一下代碼
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
Class
= {} Class.__index
= Class function
Class:new(x,y) local
temp = {} setmetatable(temp,
Class) temp.x
= x temp.y
= y return temp end function
Class.test() print ( self .x, self .y) end object = Class:new( 10 , 20 ) object :test() |
輸出的結果是:
>lua -e "io.stdout:setvbuf 'no'" "object.lua"
lua: object.lua:15: attempt to index global 'self' (a nil value)
stack traceback:
object.lua:15: in function 'test'
object.lua:21: in main chunk
[C]: ?
>Exit code: 1
從這裏的錯誤可以看出,沒有self這個參數,竟然,方法用的是點號,那我們試一下把對象傳進去看下能不能正常運行
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
Class
= {} Class.__index
= Class function
Class:new(x,y) local
temp = {} setmetatable(temp,
Class) temp.x
= x temp.y
= y return temp end function
Class.test() print ( self .x, self .y) end object = Class:new( 10 , 20 ) object :test( object ) |
遺憾的是這樣的改動是錯誤的,錯誤的結果也是一樣的
>lua -e "io.stdout:setvbuf 'no'" "object.lua"
lua: object.lua:15: attempt to index global 'self' (a nil value)
stack traceback:
object.lua:15: in function 'test'
object.lua:21: in main chunk
[C]: ?
>Exit code: 1
那我們這次嘗試下想剛纔那樣,把方法的點號搞成一致看下效果怎樣
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
Class
= {} Class.__index
= Class function
Class:new(x,y) local
temp = {} setmetatable(temp,
Class) temp.x
= x temp.y
= y return temp end function
Class.test() print ( self .x, self .y) end object = Class:new( 10 , 20 ) object .test() |
遺憾的是跟之前不一樣,還是不能運行
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
Class
= {} Class.__index
= Class function
Class:new(x,y) local
temp = {} setmetatable(temp,
Class) temp.x
= x temp.y
= y return temp end function
Class.test() print ( self .x, self .y) end object = Class:new( 10 , 20 ) object .test() |
1
|
|
1
|
回想一下,冒號的作用可以傳遞一個實參,對於方法的操作我們需要一個接受者,那麼進行以下的改動 |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
Class
= {} Class.__index
= Class function
Class:new(x,y) local
temp = {} setmetatable(temp,
Class) temp.x
= x temp.y
= y return temp end function
Class:test() print ( self .x, self .y) end object = Class:new( 10 , 20 ) object .test( object ) |
這次輸出就正常了
>lua -e "io.stdout:setvbuf 'no'" "object.lua"
10 20
>Exit code: 0
這段代碼告訴了我們,想要操作一個方法就一定需要一個額外參數來表示該值,對於點號,我們必須顯示傳遞一個實參,才能使程序正常運行,而爲了方便,我們可以直接使用冒號來簡化操作.
結論:
羅嗦了半天其實,可以用一下一句話來避免這個問題:
用lua進行面向對象的編程,聲明方法和調用方法統一用冒號,對於屬性的調用全部用點號