LUACN论坛

 找回密码
 加入我们

QQ登录

只需一步,快速开始

搜索
热搜: YJWOW MagicStone BoL
楼主: vshrd

BEE进阶研究第一季--Lua以元表元方法的形式模拟面向对象,让你的代码易读易改易维护

[复制链接]
发表于 2023-12-16 17:48:56 | 显示全部楼层
对此非常感兴趣。仔细读读
回复 支持 反对

使用道具 举报

发表于 2024-8-9 09:06:48 | 显示全部楼层
对直接打印print(me)那边不太明白
为什么定义me=myUnit:New("player")后,打印出来就包含player的信息呢,没见到myUnit:__tostring()这个函数对me进行处理啊?
不太明白
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-8-9 12:32:04 | 显示全部楼层
行了行了 发表于 2024-8-9 09:06 AM
对直接打印print(me)那边不太明白
为什么定义me=myUnit:New("player")后,打印出来就包含player的信息呢 ...

function myUnit:__tostring()--重写原方法的逻辑
    local str=string.format("名字:%s 等级:%d 血量:%d/%d 蓝量:%d/%d",self.name,self.lv,self.hp,self.maxHp,self.mp,self.maxMp)
    return str
end

你可以理解为print(XX)的这个方法
其实XX是一个字符串
而我们给他的参数不是字符串而是一个对象
那么底层就会自动对这个对象去寻找__tostring()方法来获取到一个字符串
回复 支持 反对

使用道具 举报

发表于 2024-8-9 14:53:55 | 显示全部楼层
vshrd 发表于 2024-8-9 12:32 PM
function myUnit:__tostring()--重写原方法的逻辑
    local str=string.format("名字:%s 等级:%d 血量: ...

又读了一遍大佬前文的print(1+2)的例子终于明白了
_tostring也是一个底层的方法
function myUnit:__tostring() 相当于重新定义了底层方法
之所以没有写成 function __tostring()是不是因为上面的那种写法仅仅将重新的逻辑限制到myUnit这个对象?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-8-9 15:02:31 | 显示全部楼层
行了行了 发表于 2024-8-9 02:53 PM
又读了一遍大佬前文的print(1+2)的例子终于明白了
_tostring也是一个底层的方法
function myUnit:__tos ...

不- -不是这个对象
而是这个抽象类
换句话说所有通过myUnit这个类所实例化的对象的底层__tostring()方法都被重写了
回复 支持 反对

使用道具 举报

发表于 2024-8-9 15:20:06 | 显示全部楼层
vshrd 发表于 2024-8-9 03:02 PM
不- -不是这个对象
而是这个抽象类
换句话说所有通过myUnit这个类所实例化的对象的底层__tostring()方 ...

明白了,又学到的新知识,感谢
回复 支持 反对

使用道具 举报

发表于 2024-8-22 17:47:42 | 显示全部楼层
做个学习记录,也供其他人参考,请大佬点评。
[Lua] 纯文本查看 复制代码
--前面省略
 
function myUnit:__tostring()--重写原方法的逻辑
    local str=string.format("名字:%s 等级:%d 血量:%d/%d 蓝量:%d/%d",self.name,self.lv,self.hp,self.maxHp,self.mp,self.maxMp)
    return str
end
 
local me=myUnit:New("player")
local tar=myUnit:New("target")
  
print(me)

打印的结果会是这样:名字:xiaoyao1 等级:85 血量:105823/105823 蓝量:100/100
看到这里有点迷糊,如果没有myUnit:__tostring()这个function,那打印结果将会是这种形式:table: 33DFBEB0。好像没见这个调用myUnit:__tostring()?为什么这里打印会是这个结果
好吧,经各种查资料,加上我七零八落粗浅拼凑的理解,我觉得是这样:使用print打印一个对象时,print函数总会调用tostring方法来格式化输出。如果元表有__tostring键,则执行__tostring键对应的方法,如果没有则看元表有没有__name键,返回__name键对应的字符串,修改表的输出逻辑。
这话如何理解呢,用print就会调用tostring方法,本来tostring就是做格式转化,把不是字符串的数据转化为字符串,如果是表格,就做了个不懂的递归处理,就是根据表格的数据,输出成table: 33DFBEB0这种格式。那现在,在此脚本里(能说是chunk吗),给了个__tostring的方法,就会优先使用这个方法,只要有这些数据,那就会输出这种格式的字符串来。
那至于print这个函数是啥样呢,调用了哪些方法?print是Lua 的内置函数并没有开源,因为它是 Lua 解释器的一部分,不是用 Lua 编写的,如果真要看,就要去看Lua的源码,我是没去看,有同学看了可以告诉我。
到这里,想必是可以回答以上的问题了。



回复 支持 反对

使用道具 举报

发表于 2024-8-22 18:03:02 | 显示全部楼层
行了行了 发表于 2024-8-9 09:06 AM
对直接打印print(me)那边不太明白
为什么定义me=myUnit:New("player")后,打印出来就包含player的信息呢 ...

哈哈,你的问题刚好我写了一个,去看看。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-8-22 18:16:58 | 显示全部楼层
xiaoyao1 发表于 2024-8-22 05:47 PM
做个学习记录,也供其他人参考,请大佬点评。[mw_shl_code=lua,true]--前面省略

function myUnit:__tos ...

嗯~!
没问题
只是那个递归处理?
我觉得应该是元方法的__tostring直接返回了该类的首地址
所以才会打印出一个table:xxxxxxxx
回复 支持 反对

使用道具 举报

发表于 2025-9-18 14:24:20 | 显示全部楼层
function myUnit:__tostring()
这样写的好处是不是新定义的tostring()指针对于myUnit,不会影响到其他的表,print在打印myUnit时就会调用新定义的tostring()?不知道理解的对不对
楼主能不能说说后面备注的那段话:
“但面向对象是自己的数据自己管理,自己的方法自己管理.
进行修改几乎不会有什么冲突,甚至根本不需要修改,直接做一个新的方法来适配新的环境即可
可读性上也因为结构的原因完全不存在阅读成本.”
能举一个具体的例子嘛?
比如我们写脚本是基本是根据几个技能的优先级施放顺序来写,每个技能都是符合那些条件来施放,比如A,B,C三个技能,优先级是A>B>C,那么通常会这样写:
if condtion1 then A end
if condition2 then B end
if condition3 then C end
如果用面向对象的写法怎么写呢?
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 加入我们

本版积分规则

小黑屋|手机版|Archiver|LUACN论坛

GMT+8, 2026-5-31 04:13 AM , Processed in 0.034364 second(s), 29 queries , Gzip On, Redis On.

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表