面向对象
面向对象的三大特性:封装、继承、多态。
-
封装:就是把对象的属性和行为(数据)结合为一个独立的整体,并尽可能隐藏对象的内部实现细节。
-
继承:从已有的类中派生出新的类称为子类,子类继承父类的数据属性和行为,并能根据自己的需求扩展出新的行为,可以提高代码的复用性。
-
多态:指允许不同的对象对同一消息做出响应。即同一消息可以根据发送对象的不同而采用多种不同的行为方式(发送消息就是函数调用)。
1.封装。
在Lua中,使用table可以很简单的封装属性和方法
--封装
Object={}
Object.name="基类" --相当于定义基类的变量
function Object:Test() --相当于定义基类的方法
print(self.name)
end
--new方法:创建这个基类的对象
function Object:new()
local obj = {}
self.__index = self
setmetatable(obj, self)
return obj
end
Animal= Object:new() --相当于Object Animal= new Object();
print(Animal.name) --输出(基类)
Animal:Test() --输出(基类)
Animal.name = "子类"
Animal:Test() --输出(子类)
但是还是没有封装,因为我们可以这样写:
Animal.id=1
print(Animal.id)--输出(1)
也就是说在Lua中new了一个新对象,并且能新加入一些变量和方法,这些特性明显是继承了父类的子类才有的,如果我们想要完全实现封装还能加一个垃圾列表garbage,利用原方法__newindex来实现:
--封装
Object={}
Object.name="基类" --相当于定义基类的变量
--垃圾列表
garbage={}
function Object:Test() --相当于定义基类的方法
print(self.name)
end
--new方法:创建这个基类的对象
function Object:new()
local obj = {}
self.__index = self
self.__newindex = garbage --垃圾列表
setmetatable(obj, self)
return obj
end
Animal= Object:new() --相当于Object Animal= new Object();
print(Animal.name) --输出(基类)
Animal:Test() --输出(基类)
Animal.name = "子类"
Animal:Test() --输出(nil)
2.继承
想要重写父类的一些方法而非直接使用它们,就需要继承,继承的实现主要运用了元表的相关知识,当我们访问table
中一个不存在的字段时,如果表中不存在该字段,则会查找它元表的__index
元方法,元方法中有这个字段则返回其值,反则返回nil
3.多态
多态就是对于一个父类的相同方法,子类可以执行不同的逻辑。
1.重写和重载方法
--创建子类
Object:SubClass("Animal")
Object:SubClass("Person")
--重写基类方法
function Animal:Test()
print("我是动物")
end
function Person:Test()
print("我是人类")
end
--调用
Animal:Test() --输出(我是动物)
Person:Test() --输出(我是人类)
如果想要调用父类方法的话:
--SubClass:可以丢进全局表中
function Object:SubClass(className)
_G[className] = {}
local obj = _G[className]
self.__index = self
--直接把父类表存进子类的base
obj.base = self
setmetatable(obj , self)
end
--定义子类Person
Object:SubClass("Person")
--重写父类方法
function Person:Test()
print("我是人类")
end
Person:Test() --输出(我是人类)
Person.base:Test() --输出(基类)
function Person:Test()
--在继承了父类的方法的基础之上重写
self.base:Test()
print("我是人类")
end
Person:Test() --输出(基类\n我是人类)
修改一些变量时:
--定义子类Person
Object:SubClass("Person")
Object:SubClass("Animal")
function Person:Test()
--不能写成self.base:Test()否则传入的是self.base
self.base.Test(self)
print("我是人类")
end
function Animal:Test()
self.base.Test(self)
print("我是动物")
end
Person:Test() --输出(1 我是人类)
Person:Test() --输出(2 我是人类)
Animal:Test() --输出(1 我是动物)
Animal:Test() --输出(2 我是动物)
Person:Test() --输出(3 我是人类)
Person:Test() --输出(4 我是人类)
2.实现接口
3.实现抽象类和抽象方法