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
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提供了用冒號的方式在一個方法定義中添加一個額外的參數,以及在一個方法調用中添加一個額外的實參
然后代碼改成
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
如果,就這么完的話,本來是一件很歡樂的事情,但是,我嘗試了一下以下代碼
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
代碼正常運行….這個讓人很費解,本來,點號對方法的操作是需要一個額外的接受者,第一段代碼已經說明了這個問題,但是,現在程序有正常運行,令我真是有點費解…
然后,我接著嘗試又發現
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
這個只不過跟第一段代碼點號和冒號的位置調換了一下,就出現了這樣的結果…
如果,你仔細想想,這里和第一段代碼的區別,可以發現,其實,這里就可以證明了冒號其實就是默認傳了一個實參到方法中
為了證明冒號的作用,我改動了一下代碼
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這個參數,竟然,方法用的是點號,那我們試一下把對象傳進去看下能不能正常運行
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
那我們這次嘗試下想剛才那樣,把方法的點號搞成一致看下效果怎樣
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()
遺憾的是跟之前不一樣,還是不能運行
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()
?
回想一下,冒號的作用可以傳遞一個實參,對于方法的操作我們需要一個接受者,那么進行以下的改動
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進行面向對象的編程,聲明方法和調用方法統一用冒號,對于屬性的調用全部用點號
?
搞這么多其實,只是加深理解罷了…歡迎交流和批評..
?