Lua面向对象
Lua 面向对象
面向对象概述
面向对象编程技术是目前最常用的编程技术之一。目前大量的编程语言都支持面向对象的特性:
- C++
- Java
- Objective-C
- Smalltalk
- C#
- Ruby
面向对象的特征
- 类(class):类是可以创建对象,并为状态(成员变量)提供初值及行为实现的可扩展模板。
- 对象(objects):对象是类的实例,每个对象都有独立的内存区域。
- 继承(inheritance):继承用于描述一个类的变量和函数被另一个类继承的行为。
- 封装(encapsulation):封装是指将数据和函数组织在一个类中。外部可以通过类的方法访问内中的数据。封装也被称之为数据抽象。
在 Lua 中,我们可以使用表和函数实现面向对象。将函数和相关的数据放置于同一个表中就形成了一个对象。继承可以用元表实现,它提供了在父类中查找存在的方法和变量的机制。
Lua 中的表拥有对象的特征,比如状态和独立于其值的标识。两个有相同值的对象(表)是两个不同的对象,但是一个对象在不同的时间可以拥有不同的值。与对象一样,表拥有独立于其创建者和创建位置的生命周期。
一个真实世界的例子
面向对象已经是一个广泛使用的概念,但是你需要正确清楚地理解它。
让我们看一个数学方面的例子。我们经常需要处理各种形状,比如圆、矩形、正方形。
这些形状有一个共同的特征——面积。所以,所有其它的形状都可以从有一个公共特征——面积的基类扩展而来。每个对象都可以有它自己的特征和函数,比如矩阵有属性长、宽和面积,printArea 和 calculateArea 方法。
创建一个简单的类
下面例子实现了矩阵类的三个属性:面积、长和宽。它还同时实现了输出面积的函数 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
创建对象
创建对象即是为类的实例分配内存空间的过程。每个对象都有自己独立的内存区域,同时还会共享类的数据。
r = Rectangle:new(nil,10,20)
访问属性
我们可以使用点操作符访问类中属性。
print(r.length)
访问成员方法
使用冒号操作符可以访问对象的成员方法,如下所示:
r:printArea()
初始化阶段,调用函数为对象分配内存同时设置初值。这与其它与面向对象的语言中的构造器很相似。其实,构造器本身也就和上面的初始化代码一样,并没有什么特别之处。
完整的例子
让我们一起看一个 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()
运行上面的程序,我们可以得到如下的输出结果:
The area is 100
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
我们从上面的类中扩展出正方形类,如下所示:
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
继承的完整示例
在元表的帮助下,我们可以使用新的 new 方法实现类的扩展(继承)。子类中保存了所有基类的成员变量和方法。
-- 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
上面的例子中,我们继承基类 Shape 创建了两个子类 Rectange 与 Square。在子类中可以重写基类提供的方法。在这个例子中,子类重写了 printArea 方法。