## 17.1 類
類是什么?一個類就是一個創建對象的模具。例如C++中,每個對象都是某個特定類的實例。在C++中,如果一個類沒有進行實例化,那這個類中對應的操作,基本就是一堆“沒有用”的代碼;**而Lua則不一樣,即使你不實例化一個“類”,你照樣也可以使用“類”名直接調用它的方法**(對于C++,請忽視靜態的方法);這說明Lua中的“類”的概念與C++這種高級語言中類的概念還是有差別的。在Lua中則沒有類的概念,而我們都是通過Lua現有的支持,去模擬類的概念。**在Lua中,要表示一個類,只需創建一個專用作其他對象的原型(prototype)。**原型也是一種常規的對象,也就是說我們可以直接通過原型去調用對應的方法。當其它對象(類的實例)遇到一個未知操作時,原型會先查找它。
在Lua中實現原型是非常簡單的,比如有兩個對象a和b,要讓b作為a的原型,只需要以下代碼就可以完成:
```lua
setmetatable(a, {__index = b}) -- 又是元表,不會的請看前幾篇關于元表的文章
```
設置了這段代碼以后,a就會在b中查找所有它沒有的操作。若將b稱為是對象a的“類”,就僅僅是術語上的變化。現在我就從最簡單的開始,要創建一個實例對象,必須要有一個原型,就是所謂的“類”,看以下代碼:
```lua
local Account = {} -- 一個原型
```
好了,現在有了原型,那如何使用這個原型創建一個“實例”呢?接著看以下代碼:
```lua
function Account:new(o) -- 這里是冒號哦
o = o or {} -- 如果用戶沒有提供table,則創建一個
setmetatable(o, self)
self.__index = self
return o
end
```
當調用Account:new時,self就相當于Account。接著,我們就可以調用Account:new來創建一個實例了。再看:
```lua
local a = Account:new{value = 100} -- 這里使用原型Account創建了一個對象a
a:display()
```
上面這段代碼是如何工作的呢?首先使用Account:new創建了一個新的實例對象,并將Account作為新的實例對象a的元表。再當我們調用a:display函數時,就相當于a.display\(a\),冒號就只是一個“語法糖”,只是一種方便的寫法。我們創建了一個實例對象a,當調用display時,就會查找a中是否有display字段,沒有的話,就去搜索它的元表,所以,最終的調用情況如下:
```lua
getmetatable(a).__index(display(a))
```
所以,其實我們可以看到的是,實例對象a表中并沒有display方法,而是繼承自Account方法的,但是傳入display方法中的self確是a。這樣就可以讓Account(這個“類”)定義操作。除了方法,a還能從Account繼承所有的字段。
繼承不僅可以用于方法,還可以作用于字段。因此,一個類不僅可以提供方法,還可以為實例中的字段提供默認值。看以下代碼:
```lua
local Account = {value = 0}
function Account:new(o) -- 這里是冒號哦
o = o or {} -- 如果用戶沒有提供table,則創建一個
setmetatable(o, self)
self.__index = self
return o
end
function Account:display()
self.value = self.value + 100
print(self.value)
end
local a = Account:new{} -- 這里使用原型Account創建了一個對象a
a:display() --100
a:display() --200
```
在Account表中有一個value字段,默認值為0;當我創建了實例對象a時,并沒有提供value字段,在display函數中,由于a中沒有value字段,就會查找元表Account,最終得到了Account中value的值,等號右邊的self.value的值就來源自Account中的value。調用a:display\(\)時,其實就調用以下代碼:
```lua
a.display(a)
```
在display的定義中,就會變成這樣子:
```lua
a.value = getmetatable(a).__index(value) + 100
```
第一次調用display時,等號左側的self.value就是a.value,就相當于在a中添加了一個新的字段value;當第二次調用display函數時,由于a中已經有了value字段,所以就不會去Account中尋找value字段了。
- 1 Lua介紹及環境
- 2 基本語法
- 3 數據類型
- 4 Lua 變量
- 5 循環
- 6 流程控制
- 7 函數
- 8 運算符
- 9 字符串
- 10 數組
- 11 迭代器
- 12 table
- 13 Lua 模塊與包
- 14 Lua 元表(Metatable)
- 14.1 元表案例
- 15 Lua 協同程序(coroutine)
- 16 Lua 文件IO
- 17 Lua 面向對象
- 17.1 類
- 17.2 繼承
- 17.3 封裝
- 18 Lua 與 Mysql
- 19 Lua 與 redis
- 20 Lua 與 JSON
- 21 Lua 與 http
- 22 Lua 與 Nginx
- 22.1 Nginx_Lua的安裝及環境
- 22.2 ngx_lua API(全表)
- 22.3 常用命令介紹
- 22 Lua 人工智能
- (1) Torch的安裝
- (2)Tensor
- Lua與C混合編程