如何为__index是函数的Lua类实现继承

  • 本文关键字:Lua 实现 继承 index 函数 c++ lua
  • 更新时间 :
  • 英文 :


通过本教程,Lua可以通过向__index指向基类表的派生类表分配元表来实现继承,如下所示:

BaseClass = {}
function BaseClass:foo()
end
DerivedClass = {}
setmetatable(DerivedClass, {__index=BaseClass}) -- set inheritance here
derived_instance = {}
setmetatable(derived_instance, {__index=DerivedClass})
derived_instance:foo() -- derived_instance can call BaseClass method foo()

然而,Lua中的面向对象也可以通过指向函数的元表__index来实现。这提供了更好的灵活性,但我不知道如何实现继承。这个测试代码演示了我的想法,但它无法运行:

#include <juce_core/juce_core.h>
#include <lauxlib.h>
#include <lualib.h>
int BaseClass_foo( lua_State* lua )
{
juce::Logger::writeToLog( "BaseClass_foo called" );
return 0;
}
int BaseClass( lua_State* lua )
{
juce::Logger::writeToLog( "BaseClass called" );
const char* key = lua_tostring( lua, 2 );
if ( strcmp( key, "foo" ) == 0 )
lua_pushcfunction( lua, BaseClass_foo );
else
lua_pushnil( lua );
return 1;
}
int DerivedClass( lua_State* lua )
{
juce::Logger::writeToLog( "DerivedClass called" );
lua_pushnil( lua );
return 1;
}
const char* lua_src =
"obj={}n"
"setmetatable(obj, {__index=DerivedClass})n"
"obj:foo()";
int main()
{
lua_State* lua = luaL_newstate();
luaL_openlibs( lua );
lua_pushcfunction( lua, BaseClass );
lua_setglobal( lua, "BaseClass" );
lua_pushcfunction( lua, DerivedClass );
lua_setglobal( lua, "DerivedClass" );
// set inheritance by metatable on class function
lua_getglobal( lua, "DerivedClass" );
lua_createtable( lua, 0, 0 );
lua_pushstring( lua, "__index" );
lua_getglobal( lua, "BaseClass" );
lua_settable( lua, -3 );

lua_setmetatable( lua, -2 );
// run lua code
int load_re = luaL_loadstring( lua, lua_src );
if ( load_re == LUA_OK )
lua_call( lua, 0, 0 );
else
juce::Logger::writeToLog( "Lua source load failed with " + juce::String( load_re ) + ": " + lua_tostring( lua, -1 ) );
lua_close( lua );
}

结果,Lua声明了一个错误,即不能对nil值调用foo,根本不调用BaseClass函数。这里打破了元索引搜索链,不同于Lua在DerivedClass表中不存在键的情况下自动搜索BaseClass表的表实现类系统。有没有办法让Lua继续解释绑定到DerivedClass的元表?

如果有人索引DerivedClass.foo,那么__index函数必须返回BaseClass.foo

如果__index是一个表,那么你基本上是这样做的:

getmetatable(DerivedClass).__index:foo()

归结为CCD_ 10

如果__index是一个函数,您可以这样做:

getmetatable(DerivedClass).__index(DerivedClass, "foo")()

因此,您的__index函数必须为键参数"返回BaseClass.foo;foo";以具有相同的效果。

最新更新