Lua进阶教程(三)面向对象编程
OOP简介
面向对象编程(OOP)是现代编程时代最常用的编程技术之一。 有许多支持OOP的编程语言,其中包括:
-
C++
-
Java 语言
-
Objective-C
-
Smlltalk
-
C#
-
Ruby
OOP的特点
-
类-一个类是创建对象的可扩展模板,为状态(成员变量)和行为的实现提供初始值。
-
对象 -它是类的实例,为自己分配了单独的内存。
-
继承-这是一个概念,通过这个概念,一个类的变量和函数被另一个类继承。
-
封装-它是在类中组合数据和函数的过程。 在函数的帮助下,可以在类外访问数据。 也称为数据抽象。
Lua中的OOP
借助Lua的表和一等公民的函数,可以在Lua中实现面向对象。 通过将函数和相关数据放入表中,形成了一个对象。 继承可以在元表的帮助下实现,为父对象中不存在的函数(方法)和字段提供一种查找机制。
Lua中的表具有对象的特征,如状态和身份标识,与其值无关。 两个具有相同值的对象(表)是不同的对象,而一个对象可以在不同的时间具有不同的值,但它总是相同的对象。 与对象一样,表的生命周期与谁创建它们或在哪里创建它们无关。
现实世界的例子
面向对象的概念被广泛使用,需要清楚地理解,才能够获得适当和最大的好处。
考虑一个简单的数学例子。 我们经常遇到处理不同形状的情况,如圆形、矩形和正方形。
形状可以有一个共同的属性:面积。 因此,我们可以用公共属性面积从基本对象形状扩展其他形状。 每个形状都可以有自己的属性和函数,例如矩形可以具有属性长度、宽度、面积,以及printArea
和 calculateArea
函数。
创建一个简单的类
下面例子实现一个矩形类,具有三个属性:面积、长度和宽度。 它还有一个printArea
函数来打印计算的面积:
calculated.
-- Meta class
Rectangle = {area = 0, length = 0, breadth = 0}
-- Derived class method 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
-- Derived class method printArea
function Rectangle:printArea ()
print(”The area of Rectangle is “,self.area)
end
创建一个对象
创建对象是为类实例分配内存的过程。每个对象都有自己的内存,并共享公共类数据:。
r = Rectangle:new(nil,10,20)
访问属性
可以使用点运算符访问类中的属性,如下所示:
print(r.length)
访问成员函数
可以使用带有对象的冒号运算符访问成员函数,如下所示:
printArea()
分配内存并设置初始值。可以将初始化过程可以与其他面向对象语言的构造函数进行比较,它只不过是一个能够设置值的函数,如上所示。
OOP 完整示例
-- Meta class
Shape = { area = 0 }
-- Base class method 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
-- Base class method printArea
function Shape:printArea()
print("The area is ", self.area)
end
-- Creating an object
myshape = Shape:new(nil, 10)
myshape:printArea()
-- Square class extending Shape
Square = Shape:new()
-- Derived class method new
function Square:new(o, side)
o = o or Shape:new(o, side)
setmetatable(o, self)
self.__index = self
return o
end
-- Derived class method printArea
function Square:printArea()
print("The area of square is ", self.area)
end
-- Creating an object
mysquare = Square:new(nil, 10)
mysquare:printArea()
-- Rectangle class extending Shape
Rectangle = Shape:new()
-- Derived class method 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
-- Derived class method printArea
function Rectangle:printArea()
print("The area of Rectangle is ", self.area)
end
-- Creating an object
myrectangle = Rectangle:new(nil, 10, 20)
myrectangle:printArea()
运行上述程序时,将得到以下输出:
The area is 100
The area of square is 100
The area of Rectangle is 200
Lua的继承
继承是将形状等简单基础对象扩展到矩形、正方形等的过程。现实世界中经常使用继承共享和扩展基本属性和函数:
看看一个简单的类扩展。如下所示:
-- Meta class
Shape = {area = 0}
-- Base class method 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
-- Base class method printArea
function Shape:printArea ()
print(”The area is “,self.area)
end
现在可以将形状扩展到正方形类,如下所示:
Square = Shape:new()
-- Derived class method new
function Square:new (o,side)
o = o or Shape:new(o,side)
setmetatable(o, self)
self.__index = self
return o
end
函数覆盖
可以覆盖基类函数,而不是使用基类中的函数,派生类可以有自己的实现,如下所示:
-- Derived class method printArea
function Square:printArea ()
print(”The area of square is “,self.area)
end
继承完整示例
在Lua中,借助元表和另一个新方法 ,我们可以扩展上述简单类的实现,在派生类中继续保留基类的所有成员变量和函数 。如下代码所示:
-- Meta class
Shape = {area = 0}
-- Base class method 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
-- Base class method printArea
function Shape:printArea ()
print(”The area is “,self.area)
end
-- Creating an object
myshape = Shape:new(nil,10)
myshape:printArea()
Square = Shape:new()
-- Derived class method new
function Square:new (o,side)
o = o or Shape:new(o,side)
setmetatable(o, self)
self.__index = self
return o
end
-- Derived class method printArea
function Square:printArea ()
print(”The area of square is “,self.area)
end
-- Creating an object
mysquare = Square:new(nil,10)
mysquare:printArea()
Rectangle = Shape:new()
-- Derived class method 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
-- Derived class method printArea
function Rectangle:printArea ()
print(”The area of Rectangle is “,self.area)
end
-- Creating an object
myrectangle = Rectangle:new(nil,10,20)
myrectangle:printArea()
运行上述程序时,将得到以下输出:
The area is 100
The area of square is 100
The area of Rectangle is 200
在上面的示例中,我们从基类Square创建了两个派生类-矩形和正方形。可以在派生类中覆盖基类的函数。在本例中,派生类覆盖了函数printArea
。