我找到了这个教程:http://lua-users.org/wiki/InheritanceTutorial
我有一个叫做生物的元词。 Creature在其构造函数中需要一个参数。 必需参数是表示名称的字符串。
local creature = Creature(name)
getDescription()
。getDescription ()
返回一个字符串:“这是一个生物”。 getName ()
返回一个字符串:名称我想创建一个名为Player
的新metatable(类)并让它继承Creature
metatable(class)
我希望能够做到以下几点:
local creature = Creature("Bob")
print(creature:getDescription())
print(creature:getName())
local player = Player("Joey")
print(player:getDescription())
print(player:getName())
应打印:
这是一个生物
鲍勃
这是一名球员 乔伊
基本上,我的问题是Creature类需要一个参数来识别某人,一个名字。它的getName ()
函数使用参数中的值并打印它。如果我要使用Player继承Creature的所有功能(并在必要时覆盖),我如何更改代码以确保Player获得所需的参数?
从教程中获取的代码:
-- Create a new class that inherits from a base class
--
function inheritsFrom( baseClass )
-- The following lines are equivalent to the SimpleClass example:
-- Create the table and metatable representing the class.
local new_class = {}
local class_mt = { __index = new_class }
-- Note that this function uses class_mt as an upvalue, so every instance
-- of the class will share the same metatable.
--
function new_class:create()
local newinst = {}
setmetatable( newinst, class_mt )
return newinst
end
-- The following is the key to implementing inheritance:
-- The __index member of the new class's metatable references the
-- base class. This implies that all methods of the base class will
-- be exposed to the sub-class, and that the sub-class can override
-- any of these methods.
--
if baseClass then
setmetatable( new_class, { __index = baseClass } )
end
return new_class
end
答案 0 :(得分:3)
我希望能够做到以下几点:
local creature = Creature("Bob") print(creature:getDescription()) print(creature:getName()) -- ...
在lua中支持这种类使用语法肯定是可能的 - 这只是一个如何使用语言机制和工具来实现这一点的问题。要决定的一些重要问题:
在wiki教程中,new_class:create()
创建了一个新实例,但没有调用任何构造函数。因此,在您的OOP系统中,您必须决定客户端代码提供的类似构造函数的函数,并且类创建将调用。例如:
function new_class:create(...)
local instance = setmetatable( {}, class_mt )
if new_class.__init__ then new_class.__init__(instance, ...) end
return instance
end
这里我只使用__init__
作为构造函数名称,类似于python,但实际上只要使用代码和类创建代码同意,任何名称都可以使用。
为了支持Creature("Bob")
,Player("Joey")
等对象创建语法,您可以使它们成为实际的函数调用,也可以使用__call
元方法。使用后者是对__call
的简单分配:
function inheritsFrom( baseClass )
local new_class = setmetatable( {}, { __index = baseClass } )
-- ...
getmetatable(new_class).__call = new_class.create
return new_class
end
对于最后一个问题,您只需在派生类中为其指定一个新函数,即可覆盖现有方法。例如。因此,要覆盖getDescription
中的Player
,您可以执行以下操作:
function Player:getDescription()
return "Is a player"
end
将所有内容放在一起,inheritsFrom
function inheritsFrom( baseClass )
local new_class = setmetatable( {}, { __index = baseClass } )
local class_mt = { __index = new_class }
function new_class:create(...)
local instance = setmetatable( {}, class_mt )
if new_class.__init__ then new_class.__init__(instance, ...) end
return instance
end
getmetatable(new_class).__call = new_class.create
return new_class
end
定义班级Creature
+一个生物实例:
local Creature = inheritsFrom
{
__init__ = function(self, name) self.name = name end;
getDescription = function(self) return "Is a creature" end;
getName = function(self) return self.name end;
}
local bob = Creature "Bob"
print(bob:getDescription())
print(bob:getName())
从Player
对Creature
进行子类化并覆盖getDescription
:
local Player = inheritsFrom(Creature)
function Player:getDescription()
return "Is a player"
end
local joey = Player "Joey"
print(joey:getDescription())
print(joey:getName())
作为最后的评论,lua Penlight库已经实现了类似于我上面描述的class system,但更加功能和完整。除非这是一个练习,否则请考虑使用它而不是重新发明另一个lua OOP系统。