LUA 面向对象
类继承的实现方式有三种类式继承、原型继承、掺元继承。 lua是采用类式继承。 1. PIL中的例子 http://book.luaer.cn/_98.htm 2.云风的例子 http://blog.codingnow.com/2006/06/oo_lua.html 定义类的函数 ->类的vtbl(除ctor super new外,这3个是定义在 类.xxx 中,而不是 vtbl.xxx中 ) 访问对象的函数以及静态成员变量->obj.xxx->_class[class_type]->自己类的vtbl ???????????????????????????????? ->找不到->_class[super]->super类的vtbl ???????????????????????????????? ->....找到了后加入自己类的vtbl中,下次不用再找 定义对象的成员变量是定义到obj.xxx中的。 还有不能定义和访问类的静态变量,因为被__newindex劫持到vbtl了,再给它加__index吧。 setmetatable ( class_type,{ __newindex= function(t,k,v) vtbl[k]=v end,__index = function(t,k) return vtbl[k] end } )又因为 vbtl会把访问过的super的静态函数和变量加入,导致和c++不同的一点是部分访问过的、子类无定义的、静态变量函数,被继承了。 if super then setmetatable(vtbl,{__index= function(t,k) local ret=_class[super][k] vtbl[k]=ret return ret end }) end 类的静态变量定义到类(类对象,非对象)中。非静态的在可以在ctor中,用self.xxx的方式初始化。 AA = class(BB) AA.TYPE = "humen" --静态变量 --------以下列出所有成员变量 -- hp -- mp -- friend function AA.ctor() --需要初始化的成员变量,不需要初始化的放着任它nil不用管 self.friend = new friend end 3.middleclasshttps://github.com/kikito/middleclass/wiki?? 来自http://love2d.org/wiki/Libraries -- middleclass.lua - v2.0 (2011-09) -- Copyright (c) 2011 Enrique Garc铆a Cota -- Permission is hereby granted,free of charge,to any person obtaining a copy of this software and associated documentation files (the "Software"),to deal in the Software without restriction,including without limitation the rights to use,copy,modify,merge,publish,distribute,sublicense,and/or sell copies of the Software,and to permit persons to whom the Software is furnished to do so,subject to the following conditions: -- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -- THE SOFTWARE IS PROVIDED "AS IS",WITHOUT WARRANTY OF ANY KIND,EXPRESS OR IMPLIED,INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,DAMAGES OR OTHER LIABILITY,WHETHER IN AN ACTION OF CONTRACT,TORT OR OTHERWISE,ARISING FROM,OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -- Based on YaciCode,from Julien Patte and LuaObject,from Sebastien Rocca-Serra local _classes = setmetatable({},{__mode = "k"}) local function _setClassDictionariesMetatables(klass) local dict = klass.__instanceDict dict.__index = dict local super = klass.super if super then local superStatic = super.static setmetatable(dict,super.__instanceDict) setmetatable(klass.static,{ __index = function(_,k) return dict[k] or superStatic[k] end }) else setmetatable(klass.static,k) return dict[k] end }) end end local function _setClassMetatable(klass) setmetatable(klass,{ __tostring = function() return "class " .. klass.name end,__index = klass.static,__newindex = klass.__instanceDict,__call = function(self,...) return self:new(...) end }) end local function _createClass(name,super) local klass = { name = name,super = super,static = {},__mixins = {},__instanceDict={} } klass.subclasses = setmetatable({},{__mode = "k"}) _setClassDictionariesMetatables(klass) _setClassMetatable(klass) _classes[klass] = true return klass end local function _createLookupMetamethod(klass,name) return function(...) local method = klass.super[name] assert( type(method)=='function',tostring(klass) .. " doesn't implement metamethod '" .. name .. "'" ) return method(...) end end local function _setClassMetamethods(klass) for _,m in ipairs(klass.__metamethods) do klass[m]= _createLookupMetamethod(klass,m) end end local function _setDefaultInitializeMethod(klass,super) klass.initialize = function(instance,...) return super.initialize(instance,...) end end local function _includeMixin(klass,mixin) assert(type(mixin)=='table',"mixin must be a table") for name,method in pairs(mixin) do if name ~= "included" and name ~= "static" then klass[name] = method end end if mixin.static then for name,method in pairs(mixin.static) do klass.static[name] = method end end if type(mixin.included)=="function" then mixin:included(klass) end klass.__mixins[mixin] = true end Object = _createClass("Object",nil) Object.static.__metamethods = { '__add','__call','__concat','__div','__le','__lt','__mod','__mul','__pow','__sub','__tostring','__unm' } function Object.static:allocate() assert(_classes[self],"Make sure that you are using 'Class:allocate' instead of 'Class.allocate'") return setmetatable({ class = self },self.__instanceDict) end function Object.static:new(...) local instance = self:allocate() instance:initialize(...) return instance end function Object.static:subclass(name) assert(_classes[self],"Make sure that you are using 'Class:subclass' instead of 'Class.subclass'") assert(type(name) == "string","You must provide a name(string) for your class") local subclass = _createClass(name,self) _setClassMetamethods(subclass) _setDefaultInitializeMethod(subclass,self) self.subclasses[subclass] = true self:subclassed(subclass) return subclass end function Object.static:subclassed(other) end function Object.static:include( ... ) assert(_classes[self],"Make sure you that you are using 'Class:include' instead of 'Class.include'") for _,mixin in ipairs({...}) do _includeMixin(self,mixin) end return self end function Object:initialize() end function Object:__tostring() return "instance of " .. tostring(self.class) end function class(name,super,...) super = super or Object return super:subclass(name,...) end function instanceOf(aClass,obj) if not _classes[aClass] or type(obj) ~= 'table' or not _classes[obj.class] then return false end if obj.class == aClass then return true end return subclassOf(aClass,obj.class) end function subclassOf(other,aClass) if not _classes[aClass] or not _classes[other] or aClass.super == nil then return false end return aClass.super == other or subclassOf(other,aClass.super) end function includes(mixin,aClass) if not _classes[aClass] then return false end if aClass.__mixins[mixin] then return true end return includes(mixin,aClass.super) end使用方法: require 'middleclass' Person = class('Person') --this is the same as class('Person',Object) or Object:subclass('Person') function Person:initialize(name) self.name = name end function Person:speak() print('Hi,I am ' .. self.name ..'.') end AgedPerson = class('AgedPerson',Person) -- or Person:subclass('AgedPerson') AgedPerson.static.ADULT_AGE = 18 --this is a class variable function AgedPerson:initialize(name,age) Person.initialize(self,name) -- this calls the parent's constructor (Person.initialize) on self self.age = age end function AgedPerson:speak() Person.speak(self) -- prints "Hi,I am xx." if(self.age < AgedPerson.ADULT_AGE) then --accessing a class variable from an instance method print('I am underaged.') else print('I am an adult.') end end local p1 = AgedPerson:new('Billy the Kid',13) -- this is equivalent to AgedPerson('Billy the Kid',13) - the :new part is implicit local p2 = AgedPerson:new('Luke Skywalker',21) p1:speak() p2:speak()Person.speak(self)可以看出,也是没super的,要显式指明父类。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |