不确定为什么将一个实例方法扩展/注入到 Lua 对象中不起作用。

在这个例子中,我正在使用lunit并尝试将一个实例方法注入到LuaSocket的一个实例中,但我无法看出以下代码为什么不起作用。

-- 使用 lunit 进行单元测试
local lunit = require('lunitx')
_ENV = lunit.module('enhanced', 'seeall')

local socket = require('socket')

-- 连接到 tcp/echo 服务
local conn, connErr = socket.connect('127.0.0.1', '7')

function conn:receiveLine(...)
    local line, err = self:receive('*l')
    assert_string(line, err)
    return line
end

function conn:sendLine(...)
    local bytesSent, err = self:send(... .. '\n')
    assert_number(bytesSent, err)
    return bytesSent
end

我得到的错误信息是:

attempt to call method 'sendLine' (a nil value)

这似乎有些显而易见,但我缺少必要的细节。

点赞
用户736571
用户736571

假设 getmetatable(conn).__index == getmetatable(conn) 是混淆的来源。

在这种情况下,conn 的元表的 __index 元方法指向的表与预期不同,因此方法的解析未针对 getmetatable(conn) 中的表发生。

function setup()
    -- 更新 __index 表,而非 conn 的元表
    local mt = getmetatable(conn).__index

    function mt:receiveLine(...)
        local line, err = self:receive('*l')
        assert_string(line, err)
        return line
    end

    function mt:sendLine(...)
        local bytesSent, err = self:send(... .. '\n')
        assert_number(bytesSent, err)
        return bytesSent
    end
end

我通过测试以查看 __index 是否指向 conn 的元表来推断出这一点,但实际上它没有:

assert_equal(getmetatable(conn), getmetatable(conn).__index)

一般地,如果 getmetatable(conn) 上存在 __newindex 处理程序来拦截新表条目,则使用 rawset()__index 的表上。

2013-09-15 05:21:51