Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ---------------------------------------------------------------------------------------------
- --[[
- qOOP - Quick Object Oriented Programming Library
- Copyright (C) 2011.
- Written by Roland Yonaba - E-mail: roland[dot]yonaba[at]gmail[dot]com
- Project Hosted At: http://qooplua.codeplex.com/
- qOOP is a simple and quick-written Library which offers some OOP facilities
- and syntax for Lua Programming Language.
- Version: 1.3.2
- Current Features :
- - Class creation with default methods granted
- - Static class and Final classes emulation
- - Single and Multiple Inheritance features
- - Default constructors provided with class() call as functions.
- - Access to super metamethods.
- --]]
- ----------------------------------------------------------------------------------------------
- -- Localizing some globals funcs
- local setmetatable, getmetatable, rawset, rawget, pcall, error = setmetatable, getmetatable, rawset, rawget, pcall, error
- local type ,ipairs, pairs, insert, unpack = type, ipairs, pairs, table.insert, unpack
- -- Hold the list of reserved keywords
- -- They are all part of any class, and should neither be propagated from a superclass to its subclasses
- -- nor from a class to its instances
- local reserved_keywords = {
- '__super',
- ',__sub',
- '__index',
- '__static',
- '__final',
- '__class',
- }
- -- Searches a method in a list of tables. This will be the core
- -- of multiple inheritance feature implementation
- local function call_method(method,...)
- for k in ipairs(arg) do
- local m = arg[k][method]
- if m and type(m)=='function' then return m end
- end
- return nil
- end
- -- Searches an item in a table.
- -- Returns true on success, plus the key, otherwise false.
- local function table_find(item,table)
- for k in pairs(table) do
- if table[k] == item then return true,k end
- end
- return false
- end
- -- Returns a reference-independant copy of a table
- -- Functions and reserved_keywords entries are not copied.
- local function table_copy(to,from)
- for k,v in pairs(from) do
- if not table_find(k,reserved_keywords) then
- if type(v) ~='function' then
- if type(v) == 'table' then
- if isObject(v) then
- local properties = {}
- for property,value in pairs(v) do properties[property] = value end
- local super = getmetatable(v)
- to[k] = super(properties)
- else
- to[k]={}
- table_copy(to[k],v)
- end
- else
- to[k] = v
- end
- end
- end
- end
- end
- -- Generates a new instance of a class
- local function instance(class)
- local o = {}
- table_copy(o,class)
- return setmetatable(o,class)
- end
- --- Checks if the given argument is a qOOP class
- -- @param class [table] The reference holding the qOOP class to be tested
- -- @return [boolean] True if 'class' is a qOOP class, otherwise False
- -- @usage <pre class='example'>
- -- <br>
- -- myClass = class() <br>
- -- print(isClass(myClass)) --> True <br>
- -- </pre>
- function isClass(class)
- local c = (class and class.__class)
- return (c and c==class or false)
- end
- --- Checks if the given argument is an instance from any qOOP class
- -- @param o [table] The reference holding the instance to be tested
- -- @return [boolean] True if 'o' is an instance from any qOOP class, otherwise False
- -- @usage <pre class='example'>
- -- <br>
- -- myClass = class() <br>
- -- myObject = new(myClass) <br>
- -- print(isObject(myObject)) --> True <br>
- -- </pre>
- function isObject(o)
- local mt = getmetatable(o)
- if type(o)~='table' or not mt then return false end
- local check = false
- for i,reserved in ipairs(reserved_keywords) do
- check = table_find(reserved,reserved_keywords)
- if not check then return false end
- end
- if rawget(o,'getClass') or rawget(o,'getSuperClass') then return false end
- return check
- end
- --- Checks if the given argument is an instance from a specific qOOP class
- -- @param o [table] The reference holding the instance to be tested
- -- @param class [table] The reference holding the qOOP class from which the instance should belong to
- -- @return [boolean] True if 'o' is an instance from qOOP class 'class', otherwise False
- -- @usage <pre class='example'>
- -- <br>
- -- myClass = class() <br>
- -- myObject = new(myClass) <br>
- -- print(isObjectOf(myObject, myClass)) --> True <br>
- -- </pre>
- function isObjectOf(o,class)
- if not isClass(class) then error('class is not a qOOP class!',2) end
- if not o.getClass then error('object is not a qOOP object!',2) end
- local c = o:getClass()
- return (c == class)
- end
- -- Checks class.method existence
- local function is_MemberOf(member,class)
- if not isClass(class) then error('class is not a qOOP class!',2) end
- return (class[member] and true or false)
- end
- -- Inits 'class' members/extra-members
- local function setMembers(class,arg)
- if not isClass(class) then error('class is not a qOOP class!',2) end
- table_copy(class,arg)
- return class
- end
- --- An interator function which processes all over the subclasses of a qOOP class
- -- @param class [table] The reference holding the qOOP class
- -- @return [table] a qOOP class which is a child of 'class' at each call.
- -- @usage <pre class='example'>
- -- <br>
- -- myClass = class() <br>
- -- for child_class in children(myClass) do <br>
- -- ... <br>
- -- end <br>
- -- </pre>
- function children(class)
- if not isClass(class) then error('class is not a qOOP class!',2) end
- local child = 0
- local num_child = #class.__sub
- return function()
- child = child + 1
- if child <= num_child then return class.__sub[child] end
- end
- end
- --- An interator function which processes all over the superclasses of a qOOP class
- -- @param class [table] The reference holding the qOOP class
- -- @return [table] a qOOP class which is an ancestor of 'class' at each call.
- -- @usage <pre class='example'>
- -- <br>
- -- myClass = class() <br>
- -- for ancestor_class in ancestors(myClass) do <br>
- -- ... <br>
- -- end <br>
- -- </pre>
- function ancestors(class)
- if not isClass(class) then error('class is not a qOOP class!',2) end
- local super = 0
- local num_super = #class.__super
- return function()
- super = super + 1
- if super <= num_super then return class.__super[super] end
- end
- end
- -- Basic class creation
- local function Class(...)
- local new_class = {}
- local super = {}
- if arg and #arg > 0 then
- for i,parent in ipairs(arg) do
- if parent.__final then error('Arg #'..i..' is a final qOOP class!',2) end
- insert(super,parent)
- insert(parent.__sub,new_class)
- end
- end
- new_class.__super = super
- new_class.__sub = {}
- setmetatable(new_class,{__index = function (t,m)
- return call_method(m,unpack(new_class.__super))
- end,
- __call = function(self,t)
- if self.__static then error('Cannot instantiate from static qOOP class!',2) end
- local object = instance(self)
- if t then table_copy(object,t) end
- return object
- end
- })
- new_class.__index = new_class
- new_class.__static = false
- new_class.__final = false
- new_class.__class = new_class
- --- Default class constructor. Creates and returns an instance of [class] qOOP class.
- -- @name [class]:new
- -- @param properties [table] An index-named table holding a set of properties for the new instance.
- -- @return [table] An instance of [class] qOOP class
- -- @usage <pre class='example'>
- -- <br>
- -- myClass = class() <br>
- -- myObject = myClass:new() <br>
- -- </pre>
- function new_class:new(properties)
- return new_class(properties)
- end
- --- Inits [class] qOOP class members.
- -- @name [class]:has
- -- @param members [table] An index-named table containing a collection of parameters for a qOOP class with initial values.
- -- @return [table] The qOOP class itself
- -- @usage <pre class='example'>
- -- <br>
- -- myClass = class() <br>
- -- myClass:has {classMemberOne = 1, classMemberTwo = 'Hello', ...} <br>
- -- </pre>
- function new_class:has(members)
- if not isClass(self) then error('setMembers() must be called from a qOOP class, not an instance!',2) end
- return setMembers(self,members)
- end
- --- Checks if the given argument is a member of [class] qOOP class.
- -- @name [class]:hasMember
- -- @param member [string] A string reference.
- -- @return [boolean] True if [class].member exists, otherwise returns False.
- -- @usage <pre class='example'>
- -- <br>
- -- myClass = class() <br>
- -- print(myClass:hasMember('classMember')) --> False <br>
- -- </pre>
- function new_class:hasMember(member)
- return is_MemberOf(member,self)
- end
- --- Checks if qOOP class [class] derives from the given argument 'class'.
- -- @name [class]:inherits
- -- @param class [table] A reference holding a qOOP class.
- -- @return [boolean] True if [class] derives from argument 'class', otherwise returns False.
- -- @usage <pre class='example'>
- -- <br>
- -- myClass = class() <br>
- -- myDerivedClass = class(myClass) <br>
- -- print(myDerivedClass:inherits(myClass)) --> True <br>
- -- </pre>
- function new_class:inherits(class)
- if not isClass(self) then error('inherits() must be called from a qOOP class!',2) end
- return (table_find(class,self.__super))
- end
- --- Checks if the qOOP class given as argument derives from qOOP class [class].
- -- @name [class]:ancestor
- -- @param class [table] A reference holding a qOOP class.
- -- @return [boolean] True if 'class' argument derives from [class], otherwise returns False.
- -- @usage <pre class='example'>
- -- <br>
- -- myClass = class() <br>
- -- myDerivedClass = class(myClass) <br>
- -- print(myClass:ancestor(myDerivedClass)) --> True <br>
- -- </pre>
- function new_class:ancestor(class)
- if not isClass(self) then error('ancestor() must be called from a qOOP class!',2) end
- return (table_find(class,self.__sub))
- end
- --- Returns the class from which a qOOP instance was created.
- -- @name [instance]:getClass
- -- @return [table] The qOOP class from which the calling object was instantiated or the qOOP class itself.
- -- @usage <pre class='example'>
- -- <br>
- -- myClass = class() <br>
- -- myObject = new(myClass) <br>
- -- print(myObject:getClass() == myClass) --> True <br>
- -- </pre>
- function new_class:getClass()
- return new_class
- end
- --- Returns a list of qOOP classes from which the qOOP class [class] derives.
- -- @name [class]:getAncestors
- -- @return [table] A table containing [class] ancestors.
- -- @usage <pre class='example'>
- -- <br>
- -- myClass = class() <br>
- -- myDerivedClass = class(myClass) <br>
- -- local listOfAncestors = myClass:getAncestors() <br>
- -- table.foreach(listOfAncestors, print) <br>
- -- </pre>
- function new_class:getAncestors()
- if not isClass(self) then error('getAncestors() must be called from a qOOP class!',2) end
- return (new_class.__super)
- end
- --- Returns a list of qOOP classes deriving from [class] qOOP class.
- -- @name [class]:getChildren
- -- @return [table] A table containing [class] children.
- -- @usage <pre class='example'>
- -- <br>
- -- myClass = class() <br>
- -- myDerivedClass = class(myClass) <br>
- -- local listOfChildren = myClass:getChildren() <br>
- -- table.foreach(listOfChildren, print) <br>
- -- </pre>
- function new_class:getChildren()
- if not isClass(self) then error('getChildren() must be called from a qOOP class!',2) end
- return (new_class.__sub)
- end
- --- Calls a metamethod defined in 'new_class' qOOP class ancestors.
- -- @name [class]:super
- -- @param method [string] A string reference
- -- @param ... [tables] A collection of arguments for [class]:method() metamethod.
- -- @return The result of [class]:method(...)
- -- @usage <pre class='example'>
- -- <br>
- -- myClass = class() <br>
- -- function myClass:operate(a,b) return a+b end <br>
- -- myDerivedClass = class(myClass) <br>
- -- function myDerivedClass:operate(a,b) return a-b end <br>
- -- print(myDerivedClass:operate(10,5)) --> 5 <br>
- -- print(myDerivedClass:super('operate',10,5)) --> 15 <br>
- -- </pre>
- function new_class:super(method,...)
- local parents = self.__super
- if #parents > 0 then
- local m = call_method(method,unpack(parents))
- if m then
- m(self,unpack(arg))
- else
- error('Cannot find metamethod '..method..'() in class parents!',2)
- end
- else
- error('qOOP Class has no parent!',2)
- end
- end
- return new_class
- end
- -- Final Classes
- local function finalClass(...)
- local try, catch = pcall(Class,...)
- if not try then
- error(catch,2)
- else
- catch.__final = true
- return catch
- end
- end
- -- Static Classes
- local function staticClass(...)
- local try, catch = pcall(Class,...)
- if not try then
- error(catch,2)
- else
- catch.__static = true
- return catch
- end
- end
- --- Creates and returns a qOOP class. Single and multiple inheritance are supported.
- -- @param ... [tables] Optional list of qOOP classes from which the new qOOP class will derive. Can be nil.
- -- @return [table] a qOOP class
- -- @usage <pre class='example'>
- -- <br>
- -- myClass = class() <br>
- -- </pre>
- -- @see class.final
- -- @see class.static
- function class(...) return end
- class = setmetatable( {}, {__call = function(self,...) return Class(...) end})
- --- Creates and returns a final qOOP class.Single and multiple inheritance are supported.
- -- <br/>A final class is a class from which no class can inherit.
- -- @param ... [tables] Optional list of qOOP classes from which the new qOOP class will derive. Can be nil.
- -- @return [table] a final qOOP class.
- -- @usage <pre class='example'>
- -- <br>
- -- myClass = class.final() <br>
- -- </pre>
- -- @see class
- -- @see class.static
- function class.final(...) return end
- class.final = finalClass
- --- Creates and returns a static qOOP class.Single and multiple inheritance are supported.
- -- <br/>A static class is a class from which instantiation is not possible.
- -- @param ... [tables] Optional list of qOOP classes from which the new qOOP class will derive. Can be nil.
- -- @return [table] a static qOOP class.
- -- @usage <pre class='example'>
- -- <br>
- -- myClass = class.static() <br>
- -- </pre>
- -- @see class
- -- @see class.final
- function class.static(...) return end
- class.static = staticClass
- --- Creates and returns an instance from a qOOP class.
- -- <br/>The new instance will have default class parameters.
- -- @param class [table] The qOOP class from which the new object instantiate.
- -- @param arg [table] Optional set of properties for the new instance.
- -- @return [table] An instance of 'class' qOOP class
- -- @usage <pre class='example'>
- -- <br>
- -- myClass = class() <br>
- -- myObject = new(myClass) <br>
- -- </pre>
- -- @see [class]:new
- function new(class,arg)
- if not isClass(class) then
- error('class is not a qOOP class!',2)
- end
- return class(arg)
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement