LUA中的冒號 點和self

2022-03-22 19:06:29 字數 2970 閱讀 2589

在lua程式設計中,經常會看到有時用點號定義乙個table的成員函式,有時卻用冒號,在呼叫的時候也是如此。那麼點號和冒號在使用上有什麼區別呢?它們與self之間又是什麼樣的關係呢?稍安勿躁,接下來謎底將一一為你揭開。

下面先看乙個例子

class = {}

class.__index = class

function class.new(x,y)

local cls = {}

setmetatable(cls, class)

cls.x = x

cls.y = y

return cls

endfunction class:test()

-- 等價於

-- function class.test(self)

print(self.x,self.y)

end

object = class.new(10,20)

object:test() --10 20

-- 等價於

object.test(object) --10 20

可以看到:

(1)定義的時候:class:test()與 class.test(self)是等價的;

(2)呼叫的時候:object:test() 與object.test(object)等價。

但是,一定要小心了,如果我們把例子中**做乙個小小的改動:

object = class.new(10,20)

改為object = class:new(10,20)

猜一下最終的輸出結果是什麼?

最終的輸出結果:

table: 00ffe788 10

table: 00ffe788 10

你是不是大吃一驚了,輸出的結果跟我們的預期完全就是天壤之別。那為什麼會得到這樣的輸出結果呢?深層次的原因是什麼?下面一一道來。

在這裡,我們在呼叫的時候將點號改為了冒號,使用冒號時,會隱性傳遞乙個self引數,它表示的是呼叫物件,這樣一來,class:new(10, 20)這樣的函式呼叫實際上有3個實參,分別是self,10,20,但是function calss.new(x, y)這樣用點號實現的函式定義實際上只有2個形參,這樣傳參的結果是

self ——> x

10 ——> y

20 ——> 丟棄

因此,最終我們列印出來的x和y的值就是self和10,而self實際就是table class。如果我們把class.new方法稍微修改一下如下:

function class.new(self, x,y)

local cls = {}

setmetatable(cls, class)

cls.x = x

cls.y = y

return cls

end或者改為

function class:new(x,y)

local cls = {}

setmetatable(cls, class)

cls.x = x

cls.y = y

return cls

end那麼最終輸出結果將會是我們預期的:

10 20

10 20

通過上述分析,我們可以看到,點號和冒號最主要的區別在於是否包含隱性引數self,使用冒號格式定義或呼叫函式方法時,lua會預設把呼叫者物件隱藏起來了,雖然隱藏起來了,但是我們卻不能忽略它的存在性,不管你相信不相信,它就在那裡,不左不右。而使用點號格式定義或呼叫函式方法時,所有引數都是被顯示地宣告的,不會躲躲藏藏,有多少就是多少,因此,如果我們需要傳遞呼叫者物件,那麼必須顯示宣告之。

下面來看幾個例子

例1a =

function a.fun(self) 

print(self.x)

enda.fun(a)        --輸出1,將a自己做為引數傳給fun函式的self

通過點號格式定義fun,並且通過點號呼叫函式fun。定義時顯示給出self形參用於接收呼叫者物件;呼叫時必須顯示給出呼叫者物件作為實參傳入。

例2function a:fun() 

print(self.x)

enda.fun(a)

通過冒號格式定義fun,並且通過點號呼叫fun。定義時隱藏了形參self,雖然我們看不到,但是self是客觀存在的,因此,在函式內部我們可以直接使用self;呼叫時顯示給出呼叫者物件作為實參傳入。

例3function a:fun() 

print(self.x)

enda:fun()

通過冒號格式定義和呼叫fun。定義時隱藏了形參self,呼叫時也隱藏了呼叫者物件這個實參,雖然我們看不到,但是a這個實參確確實實是被傳遞給了self。

上面討論的都是函式方法的定義和呼叫,那麼對於非函式的資料成員又是怎麼樣的呢?對於資料成員的訪問我們是否也是可以通過冒號或點號的形式來完成呢?很遺憾地告訴你,答案是否定的。

看乙個例子

girl =

function girl.gotomarket(girl ,somemoney)

girl.money = girl.money - somemoney

endgirl.gotomarket(girl ,100)

print(girl.money)

輸出結果

girl =

function girl.gotomarket(girl ,somemoney)

girl.money = girl.money - somemoney

endgirl.gotomarket(girl ,100)

print(girl:money)

輸出結果

error:function arguments expected near ')'

通過上面例子可以看到,對於非成員函式的資料成員的訪問,可以用點號的形式,但是不能用冒號的形式。

綜上所述,給出一條不成文的約定:

用lua進行物件導向的程式設計,成員方法的宣告和呼叫統一用冒號形式,對於資料成員的呼叫全部用點號形式。

LUA中的冒號 點和self

在lua程式設計中,經常會看到有時用點號定義乙個table的成員函式,有時卻用冒號,在呼叫的時候也是如此。那麼點號和冒號在使用上有什麼區別呢?它們與self之間又是什麼樣的關係呢?稍安勿躁,接下來謎底將一一為你揭開。下面先看乙個例子 class class.index class function ...

lua中的點 冒號與self

lua程式設計中,經常遇到函式的定義和呼叫,有時候用點號呼叫,有時候用冒號呼叫,這裡簡單的說明一下原理。girl function girl.gotomarket girl somemoney girl.money girl.money somemoney endgirl.gotomarket gi...

Lua中的點 冒號與self

lua中的點 冒號與self,它們之間的關係主要體現在函式的定義與呼叫上,lua在函式定義時可以用點也可以用冒號,如 function mytable.fun p return p endfunction mytable fun p return p end用冒號定義的函式有個特別的地方是它內部有個...