继承教程 |
|
以下示例实现了一个没有继承的类
SimpleClass = {} SimpleClass_mt = { __index = SimpleClass } -- This function creates a new instance of SimpleClass -- function SimpleClass:create() local new_inst = {} -- the new instance setmetatable( new_inst, SimpleClass_mt ) -- all instances share the same metatable return new_inst end -- Here are some functions (methods) for SimpleClass: function SimpleClass:className() print( "SimpleClass" ) end function SimpleClass:doSomething() print( "Doing something" ) end
在上面的示例中,SimpleClass
代表一个表,它保存了我们类中的所有方法,就像一个类声明。SimpleClass_mt
是我们将附加到每个创建的类实例的元表。函数 SimpleClass:create()
创建我们类 SimpleClass
的一个实例。创建类实例涉及创建一个空表,然后将我们的 SimpleClass
元方法附加到它。附加元方法的结果是,新实例会查看我们附加的元表以获取其自定义行为。
对实例进行方法调用将触发实例上的“索引”事件,导致在实例元表的“__index
”成员上进行查找。__index
成员只是一个对 SimpleClass
的引用。因此,对实例进行方法调用将导致在 SimpleClass
表中进行查找。
以下是一个示例
> simple = SimpleClass:create() > > simple:className() SimpleClass > > simple:doSomething() Doing something
现在我们想要创建一个新的类 SubClass
,它继承并可选地覆盖来自 SimpleClass
的函数。
-- 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
函数 inheritsFrom(baseClass)
接受一个参数,即我们要继承的类声明。该函数返回一个类声明,我们可以对其进行定制。new_class
是要返回的新类声明。嵌套函数 new_class:create()
是返回的类声明的一部分,它将创建我们正在创建的子类的新的实例。此函数创建一个 newinst
表,该表使用我们的新类表来保存其方法。新的类表反过来会在找不到我们需要的某个方法时在 baseClass
中查找,因此我们继承了它的方法。
基于 SimpleClass
,我们现在创建一个名为 SubClass
的类,它继承自 SimpleClass
并覆盖 className()
> -- Create a new class that inherits from SimpleClass > SubClass = inheritsFrom( SimpleClass ) > > -- override className() function > function SubClass:className() print( "SubClass" ) end > > -- Create an instance of SimpleClass > simple = SimpleClass:create() > > simple:className() SimpleClass > > simple:doSomething() Doing something > > -- Create an instance of SubClass > sub = SubClass:create() > > sub:className() -- Call overridden method SubClass > > sub:doSomething() -- Call base class method Doing something >
我们现在可以扩展我们的继承结构并添加其他语言中常见的特性,例如访问类的超类和提供类型 ID 功能的 isa()
方法
-- A new inheritsFrom() function -- function inheritsFrom( baseClass ) local new_class = {} local class_mt = { __index = new_class } function new_class:create() local newinst = {} setmetatable( newinst, class_mt ) return newinst end if nil ~= baseClass then setmetatable( new_class, { __index = baseClass } ) end -- Implementation of additional OO properties starts here -- -- Return the class object of the instance function new_class:class() return new_class end -- Return the super class object of the instance function new_class:superClass() return baseClass end -- Return true if the caller is an instance of theClass function new_class:isa( theClass ) local b_isa = false local cur_class = new_class while ( nil ~= cur_class ) and ( false == b_isa ) do if cur_class == theClass then b_isa = true else cur_class = cur_class:superClass() end end return b_isa end return new_class end
以及一个使用示例
> SimpleClass = inheritsFrom( nil ) -- pass nil because SimpleClass has no super class > > SubClass = inheritsFrom( SimpleClass ) > > FinalClass = inheritsFrom( SubClass ) > > sub = SubClass:create() > fc = FinalClass:create() > > print( fc:isa( SubClass ) ) true > print( fc:isa( FinalClass ) ) true > print( sub:isa( SubClass ) ) true > print( sub:isa( FinalClass ) ) false
大部分代码与上面基本相同,但简化为仅包含使“基于原型的编程”起作用所需的必要内容。更准确地说,它允许使用克隆和原型委托进行原型编程。对未在对象中设置的属性的访问被委托给它的原型。此代码使用table
表作为最基本的原型,object
作为table
的特殊化。函数object.isa
对于原型范式来说并不是严格必需的,但更方便。
clone(base_object[, clone_object]) -> table
参数
base_object
:表,要克隆的基本对象。
clone_object
:表,一个可选对象,将其转换为base_object
的克隆。
返回值
table
:新的克隆。
如果new_object
不是table
类型,则如果它不是nil
,则返回new_object
,在这种情况下返回base_object
。new_object
的元表设置为自身,并且它的__index
现在指向它的原型base_object
。clone
也可以作为object.clone
使用。
isa( clone_object, base_object) -> bool
参数
clone_object
:表,要检查的克隆
base_object
:表,clone_object
的疑似基础。
返回值
bool
:克隆在原型层次结构中具有基础。
如果两个参数都不是table
,isa
将回退到返回类型的比较。它也可以作为object.isa
使用。
function clone( base_object, clone_object ) if type( base_object ) ~= "table" then return clone_object or base_object end clone_object = clone_object or {} clone_object.__index = base_object return setmetatable(clone_object, clone_object) end function isa( clone_object, base_object ) local clone_object_type = type(clone_object) local base_object_type = type(base_object) if clone_object_type ~= "table" and base_object_type ~= table then return clone_object_type == base_object_type end local index = clone_object.__index local _isa = index == base_object while not _isa and index ~= nil do index = index.__index _isa = index == base_object end return _isa end object = clone( table, { clone = clone, isa = isa } )
-- testing "isa" foo = object:clone() bar = object:clone() baz = foo:clone() print( foo:isa(object) ) print( bar:isa(foo) ) print( baz:isa(foo) ) --[[ output: true false true ]] --testing prototype delegation foo = object:clone() bar = foo:clone() function foo:speak() print(self.thoughts or "foo has no thoughts") end bar:speak() --[[ output: foo has no thoughts ]] bar.thoughts = "I may be a clone, but I'm an individual!" bar:speak() --[[ output: I may be a clone, but I'm an individual! ]]