美文网首页
set/getmetatable与debug.set/getme

set/getmetatable与debug.set/getme

作者: 凉夜lrs | 来源:发表于2021-02-01 10:28 被阅读0次
--set/getmetatable

{"setmetatable", luaB_setmetatable},
{"getmetatable", luaB_getmetatable},

static int luaB_setmetatable (lua_State *L) {
  int t = lua_type(L, 2);
  luaL_checktype(L, 1, LUA_TTABLE);
  luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2,
                    "nil or table expected");
  if (luaL_getmetafield(L, 1, "__metatable"))
    luaL_error(L, "cannot change a protected metatable");
  lua_settop(L, 2);
  lua_setmetatable(L, 1);
  return 1;
}

static int luaB_getmetatable (lua_State *L) {
  luaL_checkany(L, 1);
  if (!lua_getmetatable(L, 1)) {
    lua_pushnil(L);
    return 1;  /* no metatable */
  }
  luaL_getmetafield(L, 1, "__metatable");
  return 1;  /* returns either __metatable field (if present) or metatable */
}
--debug.set/getmetatable

{"setmetatable", db_setmetatable},
{"getmetatable", db_getmetatable},

static int db_setmetatable (lua_State *L) {
  int t = lua_type(L, 2);
  luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2,
                    "nil or table expected");
  lua_settop(L, 2);
  lua_pushboolean(L, lua_setmetatable(L, 1));
  return 1;
}

static int db_getmetatable (lua_State *L) {
  luaL_checkany(L, 1);
  if (!lua_getmetatable(L, 1)) {
    lua_pushnil(L);  /* no metatable */
  }
  return 1;
}

可以看到,两者不同的地方在于,setmetatable 有检测 __metatable 键值,如果存在,setmetatable 会失败。而 getmetatable 会优先返回 __metatable 键值的内容,不存在再返回 metatable。举例说明:

local a = {}
setmetatable(a, {__metatable = "lock"})
print(type(getmetatable(a)), getmetatable(a))
print(type(debug.getmetatable(a)), debug.getmetatable(a))
debug.setmetatable(a, {__metatable = "lock2"})
setmetatable(a, {__metatable = "lock2"})
image.png

相关文章

网友评论

      本文标题:set/getmetatable与debug.set/getme

      本文链接:https://www.haomeiwen.com/subject/lhljtltx.html