Lua - 面向对象编程
OOP 简介
面向对象编程 (OOP) 是现代编程时代最常用的编程技术之一。有许多编程语言支持 OOP,包括:
- C++
- Java
- Objective-C
- Smalltalk
- C#
- Ruby
OOP 的特性
Class − Class 是一个可扩展的模板,用于创建对象,提供状态(成员变量)的初始值以及行为的实现。
Objects − 它是 class 的一个实例,为自身分配独立的内存。
Inheritance − 它是一种概念,通过该概念,一个 class 的变量和函数可以被另一个 class 继承。
Encapsulation − 它是将数据和函数组合在 class 内部的过程。数据可以通过函数在 class 外部访问。它也被称为数据抽象。
Lua 中的 OOP
你可以使用 Lua 的 table 和 first class function 来实现面向对象。通过将函数和相关数据放入一个 table 中,即形成了一个 object。Inheritance 可以通过 metatable 来实现,为父 object 中不存在的函数(方法)和字段提供查找机制。
Lua 中的 table 具有类似于 object 的特性,如独立于其值的状态和身份。具有相同值的两个 object(table)是不同的 object,而一个 object 在不同时间可以有不同的值,但它始终是同一个 object。像 object 一样,table 具有独立于创建者或创建位置的生命周期。
现实世界的示例
面向对象概念被广泛使用,但你需要清楚地理解它才能获得适当的最大益处。
让我们考虑一个简单的数学示例。我们经常遇到处理不同形状的情况,如圆形、矩形和正方形。
这些形状可以有一个共同属性 Area。因此,我们可以从具有共同属性 area 的基对象 shape 扩展其他形状。每种形状可以有自己的属性和函数,例如矩形可以有 length、breadth、area 作为其属性,以及 printArea 和 calculateArea 作为其函数。
创建简单 Class
下面展示了一个简单的矩形 class 实现,具有三个属性 area、length 和 breadth。它还具有一个 printArea 函数来打印计算出的面积。
-- 元类
Rectangle = {area = 0, length = 0, breadth = 0}
-- 派生类方法 new
function Rectangle:new (o,length,breadth)
o = o or {}
setmetatable(o, self)
self.__index = self
self.length = length or 0
self.breadth = breadth or 0
self.area = length*breadth;
return o
end
-- 派生类方法 printArea
function Rectangle:printArea ()
print("The area of Rectangle is ",self.area)
end
创建 Object
创建 object 是为 class 实例分配内存的过程。每个 object 都有自己的内存,并共享共同的 class 数据。
-- 创建 Rectangle class 的对象 r = Rectangle:new(nil,10,20)
访问属性
我们可以使用点运算符访问 class 中的属性,如下所示 −
-- 打印矩形的长度 print(r.length)
访问成员函数
你可以使用冒号运算符结合 object 来访问成员函数,如下所示 −
-- 调用矩形对象的 printArea() 方法 r:printArea()
内存被分配,初始值被设置。初始化过程可以与其他面向对象语言中的构造函数相比。它只是一个函数,用于设置值,如上所示。
示例 - 使用对象
让我们看一个在 Lua 中使用面向对象编程的完整示例。
main.lua
-- 元类
Shape = {area = 0}
-- 基类方法 new
function Shape:new (o,side)
o = o or {}
setmetatable(o, self)
self.__index = self
side = side or 0
self.area = side*side;
return o
end
-- 基类方法 printArea
function Shape:printArea ()
print("The area is ",self.area)
end
-- 创建一个对象
myshape = Shape:new(nil,10)
-- 调用对象的 printArea 方法
myshape:printArea()
输出
运行上述程序时,您将得到以下输出−
The area is 100
Lua 中的继承
继承是将简单的基类对象(如 shape)扩展为矩形、正方形等的进程。它在现实世界中常用于共享和扩展基本属性和函数。
让我们看一个简单的类扩展示例。下面有一个类。
-- 元类
Shape = {area = 0}
-- 基类方法 new
function Shape:new (o,side)
o = o or {}
setmetatable(o, self)
self.__index = self
side = side or 0
self.area = side*side;
return o
end
-- 基类方法 printArea
function Shape:printArea ()
print("The area is ",self.area)
end
我们可以将 shape 扩展为 square 类,如下所示。
-- 扩展 Shape 类 Square = Shape:new() -- 派生类方法 new function Square:new (o,side) o = o or Shape:new(o,side) setmetatable(o, self) self.__index = self return o end
重写基类函数
我们可以重写基类函数,即派生类可以有自己的实现,而不是使用基类中的函数,如下所示 −
-- 派生类方法 printArea
function Square:printArea ()
print("The area of square is ",self.area)
end
继承完整示例
我们可以使用 metatables 和另一个 new 方法来扩展上述 Lua 中的简单类实现。基类的所有成员变量和函数在派生类中都会保留。
main.lua
-- 元类
Shape = {area = 0}
-- 基类方法 new
function Shape:new (o,side)
o = o or {}
setmetatable(o, self)
self.__index = self
side = side or 0
self.area = side*side;
return o
end
-- 基类方法 printArea
function Shape:printArea ()
print("The area is ",self.area)
end
-- 创建一个对象
myshape = Shape:new(nil,10)
myshape:printArea()
-- 子类
Square = Shape:new()
-- 派生类方法 new
function Square:new (o,side)
o = o or Shape:new(o,side)
setmetatable(o, self)
self.__index = self
return o
end
-- 派生类方法 printArea
function Square:printArea ()
print("The area of square is ",self.area)
end
-- 创建一个对象
mysquare = Square:new(nil,10)
mysquare:printArea()
-- 创建 Shape 的子类
Rectangle = Shape:new()
-- 派生类方法 new
function Rectangle:new (o,length,breadth)
o = o or Shape:new(o)
setmetatable(o, self)
self.__index = self
self.area = length * breadth
return o
end
-- 派生类方法 printArea
function Rectangle:printArea ()
print("The area of Rectangle is ",self.area)
end
-- 创建一个对象
myrectangle = Rectangle:new(nil,10,20)
myrectangle:printArea()
输出
运行上述程序时,我们将得到以下输出 −
The area is 100 The area of square is 100 The area of Rectangle is 200
在上述示例中,我们从基类 Shape 创建了两个派生类 − Rectangle 和 Square。可以在派生类中重写基类的函数。在这个示例中,派生类重写了 printArea 函数。