最近看到了一道号称腾讯最难的lua面试题:
研究了一下答案实现的过程,发现这题主要考察了元表和元方法、面向对象、环境这三个知识点,非常值得学习。题目如下:
function class(...)
--TODO
end
--TODO补充修改实现class方法
A =
class {
name = string,
age = int,
foo = function()
print('from A', name, age)
end
}
B =
class {
__super = A,
foo = function()
print('from B', name, age)
end
}
local a = A()
a.name = 'hanmeimei'
a.age = 17
a:foo()
local b = B()
b.name = 'lilei'
b.age = 18
b:foo()
a.name = 20
a.age = '20'
b.foo = 'x'
-- 输出
-- from A hanmeimei 17
-- from B lilei 18
-- 类型不匹配:name 的类型是 string
-- 类型不匹配:age 的类型是 number
-- 函数不能赋值
(string和int必须修改,可替换为任意实值)
我觉得这题可以分为三步解决:
1、__newindex元方法实现错误赋值提示
输入:
输出:
解析:
1、若以类似函数的形式调用了一个值(table)时,则会调用它的__call元方法(此处a=A()而非a=A,因此会调用A的__call),因此用__call返回一个实例来完成a=A()的调用
2、对table中不存在的字段进行访问时,会调用__index;当对table中不存在的字段进行赋值时,会调用__newindex元。因此可构造一个不存在任何键值对的table,用data储存数据并赋值给__index,__newindex实现赋值类型检测并输出提示。
最初版本代码: