首先我们要明白面向对象是一种思想,其核心概念如下:
封装:用程序语言把一类事物的方法和属性描述出来;
继承:子类可以继承父类方法
多态:对于继承同一父类的子类其内部实现各有不同(不同的对象执行父类的同一个方法产生了不同的结果)
一、如何实现面向对象中的封装
print("people is aready")
people={ --虽然people是一个table,但是我们可以用面向对象的一个思想,将它看作一个抽象类:people类
name=nil,
age=nil
}
function people.new(cname,cage)
local p={}
p.name=cname
p.age=cage
return p
end
function people.eat()
print("eating...")
end
local zhangsan=people.new('zhangsan',15)--其实张三是一个table但是我们用面向对象的思想,将它看作对象
local lisi= people.new('lisi',20)--李四同样是people抽象类实例化出来的一个对象
print(zhangsan.name,zhangsan.age)
print(lisi.name,lisi.age)
上面的案例,我们就是把table人 以面向对象的思想来看,他就是一个人类的抽象类
而zhangsan 和 lisi 就是人类实例化后的对象
二、如何在lua中实现面向对象的继承
2.1.我们可以看到执行上面的逻辑后,p并不会执行people中的eat方法
print("people is aready")
people={ --虽然people是一个table,但是我们可以用面向对象的一个思想,将它看作一个抽象类:
people类
name=nil,
age=nil
}
function people.new(cname,cage)
local p={}
※ setmetatable(p,people)--将table p 和table people关联了起来(这样子可以让两个table实现继承的关系)
※ people.__index=people--程序去元表里寻找__index键,然后去这个键值对应的表里面寻找这个eat方法
p.name=cname
p.age=cage
return p
end
function people.eat()
print("eating...")
end
local zhangsan=people.new('zhangsan',15)--其实张三是一个table但是我们用面向对象的思想,将它看作
对象
local lisi= people.new('lisi',20)--李四同样是people抽象类实例化出来的一个对象
print(zhangsan.name,zhangsan.age)
print(lisi.name,lisi.age)
zhangsan.eat()
※2.2.Lua中“:”冒号的用法
--在lua的编程中 ":"冒号和"."的去区别是什么:
-- :表示默认传入一个变量self,所以上面的代码可以这样子更改
function people:eat()
print(self.name.."eating...")
end
zhangsan:eat()
三、通过Metatable 元表与元方法来实现多态:
在Lua中,每个table都可以关联一个metatable。metatable是一个普通的table,可以包含一些特殊的字段(也称为元方法),这些字段定义了对应操作的行为。通过设置metatable,我们可以对table对象进行元操作的重载,实现自定义的行为。
常用元方法
- __index:当访问一个table中不存在的索引时触发。
- __newindex:当给一个table中不存在的索引赋值时触发(赋值会失败)。
1.__index:
__index 主要用于对table的查询:
如果子表中的元素不存在,lua就会调用元表中的__index,去元表中查找对应的元素。
这里的元素并不局限于字段,也包括方法和table。
local tableChild={
age=20
}
local tableParent={
__index={
name='Jay',
age=25
}
}
setmetatable(tableChild,tableParent)
print(tableChild.name)--输出结果:Jay
--因为子表中没有name,所以去它的元表的index里找有没有name这个字段
print(tableChild.age)--输出结果:20
--因为子表中有age,所以直接输出子表中的value而不会再去元表中寻找覆盖
2.__newindex:
__newindex主要用于对table的赋值更新
如果想对子表中不存在的索引赋值时,lua就会调用元表中的__newindex元方法,
如果该方法是一个函数,就会执行这个方法
local animal={
name="dog"
}
local o={}
o.__newindex=function ()--给o增加一个元方法
print("__newindex Is Working")
end
setmetatable(animal,o)--给animal增加一个元表,把o作为animal的元表设置进去
animal.age=29--__newindex Is Working
--因为animal这个table中没有age这个属性,所以赋值时回去找元表,然后元表中又有__newindex这个元方法,便调用元方法
print(animal.name)--dog
print(animal.age)--nil
local b={}
local c={}
local people={
name="eason"
}
b.__newindex=c--给b增加一个__newindex元方法,这个元方法指向table c
setmetatable(people,b)--给people指定一个元表b
people.age=20
print(people.age)--nil
print(c.age)--20
--__newindex的两种用法
--1.__newindex可以指向一个方法
--2.__newindex可以指向一个table,然后将值赋给指向的table