【Lua】实现面向对象

面向对象

面向对象的三大特性:封装、继承、多态。

  • 封装:就是把对象的属性和行为(数据)结合为一个独立的整体,并尽可能隐藏对象的内部实现细节。

  • 继承:从已有的类中派生出新的类称为子类,子类继承父类的数据属性和行为,并能根据自己的需求扩展出新的行为,可以提高代码的复用性。

  • 多态:指允许不同的对象对同一消息做出响应。即同一消息可以根据发送对象的不同而采用多种不同的行为方式(发送消息就是函数调用)。

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.实现抽象类和抽象方法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值