Lua实现基本的面向对象
{:1_892:} 哈喽,我是小冰。据小冰完全没有科学的统计得知,大多数游戏都用Lua作为脚本语言。小冰学习过一段时间的Python,但突然又对Lua感兴趣,也去研究一二。
小冰喜欢在已经学习过的计算机语言的基础上进行对比,发现Lua中没有面向对象。但是,发现Lua中的table可以用 . 来访问table内的元素,再利用元表的特性给表附加方法,于是突发奇想就有了以下的代码。
function triangle(a, b, c)
--用闭包函数作为私有成员
local function isTriangle(_a, _b, _c)
if not (_a and _b and _c) then return nil end --判断是否给了三条边
if not ((_a + _b) > _c) and ((_a - _b) < _c) then return nil end
return true
end
if not isTriangle(a, b, c) then return nil end
local baseClass = {}
self = setmetatable(baseClass,{})
--初始化
self.a = a
self.b = b
self.c = c
--公有方法
function self:calcArea()
--用海伦公式计算三角形面积
local p = (self.a + self.b + self.c) / 2
local s = math.sqrt(p * (p - self.a) * (p - self.b) * (p - self.c))
return s
end
--返回对象实例
return self
end
--继承,不够再Lua中并不推荐继承。用一次就够了吧....
function StrongTriangle(a, b, c)
tri = triangle(a, b, c)
if not tri then return nil end
function tri:calcCirc()
c = tri.a + tri.b + tri.c
return c
end
return tri
end
myTriangle = triangle(3,4,5)
another = StrongTriangle(6,8,10)
print("边长为 a="..myTriangle.a.." b="..myTriangle.b.." c="..myTriangle.c)
print("面积:"..myTriangle:calcArea())
print("边长为 a="..another.a.." b="..another.b.." c="..another.c)
print("面积:"..another:calcArea())
print("周长:"..another:calcCirc())
--对比两个table地址,不一样就成功啦!!!
print(myTriangle,another)
结果:
边长为 a=3 b=4 c=5
面积:6.0
边长为 a=6 b=8 c=10
面积:24.0
周长:24
table: 003C21A8 table: 003C2270
情况看起来一切都OK嘛,在网上还有一种方式,小冰看了看,emmm感觉这种比较酷。小冰再对这个triangle在升级吧。
代码:
-- a,对边;b,邻边;c,邻边(比如靠近直角的邻边)
local function triangle(a, b, c)
--类似于__new__在初始化前进行处理
--检查边长是否合格
local function __new__(_a,_b,_c)
--利用闭包函数作为私有成员
if not (_a and _b and _c) then return nil end
if not(((_a+_b)>_c)and (_a-_b)<_c) then return nil end
return true
end
if not __new__(a, b, c) then return nil end
local _triangle = {}
--初始化,因为self作用域的原因,就定义在_triangle域内
function _triangle:__init__(a, b, c)
local ob = {}
setmetatable(ob,self)
self.__index = self
--保护基础类
self.__metatable = ob
self.__tostring = ob
self.a = a
self.b = b
self.c = c
return ob
end
function _triangle:circumference(_a, _b, _c) --周长
if __new__(_a, _b, _c) then --判断是否有输入
self.a = _a
self.b = _b
self.c = _c
end
return self.a + self.b + self.c
end
function _triangle:area()
local p = (self.a + self.b + self.c) / 2
local s = math.sqrt(p * (p - self.a) * (p - self.b) * (p - self.c))
return s
end
function _triangle:center() --内角
local s = self:area()
if s then
s = s * 2
else
return s --s = nil
end
local ret = {}
ret['C'] = math.deg(math.asin(s / (self.a * self.b))) --角C
ret['B'] = math.deg(math.asin(s / (self.a * self.c))) --角B
ret['A'] = 180 - (ret.C + ret.B) --角A
return ret
end
function _triangle:show()
print(string.format("a=%sb=%sc=%s",self.a,self.b,self.c))
print(string.format("面积:%.4f", self:area()))
print("周长:", self:circumference())
local ABC = self:center()
print("三角形三个内角A,B,C分别为:\n"..string.format("∠A = %.4f\n∠B = %.4f\n∠C = %.4f",ABC.A, ABC.B, ABC.C))
end
ret = _triangle:__init__(a, b, c)
ret.init = ret --防止再次调用重构
return ret
end
triangle(3,4,5):show()
print("**************")
triangle(2,2,math.sqrt(3)):show()
print("**************")
triangle(1,2,math.sqrt(3)):show()
print("**************")
t = triangle(1,1,math.sqrt(2))
t:show()
print("----cut line----")
--使用对象的公开方法
print("新的周长:"..t:circumference(6,6,6))
--此时已改变对象中的量
t:show()
运行结果:
a=3b=4c=5
面积:6.0000
周长: 12
三角形三个内角A,B,C分别为:
∠A = 36.8699
∠B = 53.1301
∠C = 90.0000
**************
a=2b=2c=1.7320508075689
面积:1.5612
周长: 5.7320508075689
三角形三个内角A,B,C分别为:
∠A = 64.3411
∠B = 64.3411
∠C = 51.3178
**************
a=1b=2c=1.7320508075689
面积:0.8660
周长: 4.7320508075689
三角形三个内角A,B,C分别为:
∠A = 30.0000
∠B = 90.0000
∠C = 60.0000
**************
a=1b=1c=1.4142135623731
面积:0.5000
周长: 3.4142135623731
三角形三个内角A,B,C分别为:
∠A = 45.0000
∠B = 45.0000
∠C = 90.0000
----cut line----
新的周长:18
a=6b=6c=6
面积:15.5885
周长: 18
三角形三个内角A,B,C分别为:
∠A = 60.0000
∠B = 60.0000
∠C = 60.0000
好啦,这就是小冰所了解的Lua面向对象方式。
初出茅庐,可能对某些知识了解的不够透彻,希望朋友们来教教小冰哟。
小甲鱼:Programming change the world. 本帖最后由 lovingxiaobing 于 2018-7-23 13:40 编辑
emmmm,小冰总结了一下Lua面向对象的类模板。参考一下咯。
--[[
*author:小冰哟
*ps:小冰总结出在Lua中类的模板
--]]
local function className(参数)
local function __new__(_参数)
--利用闭包函数作为私有成员
--这里对参数的处理
--如果通过。默认返回true
return true
end
if not __new__(参数) then return nil end
--通过局部定义的方式来生成不同的表
local _className = {}
--私有成员,但不可通过self操作
local var = xxx
--初始化,_className命名空间内定义self作为类的实例对象
function _className:__init__(参数)
local ob = {}
--在_className命名空间内,此时的self就_className的别名
setmetatable(ob,self)
self.__index = self
--保护基础类
self.__metatable = ob
self.__tostring = ob
--初始化对象的成员,公有成员
self.xxx = xxx
return ob
end
--公有成员
function _className:methodName(参数)
--类的实例对象self.xxx
end
local ret = _className:__init__(参数)
ret.__init__ = ret --防止再次调用重构
return ret
end
--继承(不推荐)
--缺点,不能访问父类的私有成员
local function myClassName(参数)
local _class = className(_参数)
--私有成员
local var = xxx
local function methodName(参数)
--segem.
end
--公有成员
_class.xxx = xxx
function _class:methodName(参数)
--segem.
--因为属于_className命名空间内,所以可以使用self
end
return _class
end
--实例化对象
object = className(参数)
obj = myClassName(参数)
可能存在不足,但对于小冰来说用起来暂时没什么问题,如果you有更棒的方法,欢迎在评论区留言哟,大家一起进步,一起分享知识,分享快乐。
小甲鱼:Programming changes the world. 不太懂欸
页:
[1]