继承教程 |
|
以下示例实现了一个没有继承的类
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 >
现在我们可以扩展我们的继承结构并添加其他语言中常见的特性,例如访问类的超类以及提供类型标识符功能的 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: table,要克隆的基础对象。clone_object: table,一个可选对象,用于将其转换为 base_object 的克隆。返回值
table: 新的克隆。如果 new_object 的类型不是 table,则返回 new_object(如果它不是 nil),在这种情况下返回 base_object。new_object 的元表被设置为它自己,并且它的 __index 现在指向它的原型 base_object。clone 也可作为 object.clone 使用。
isa( clone_object, base_object) -> bool参数
clone_object: table,要检查的克隆base_object: table,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! ]]