lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


On Tue, Feb 9, 2010 at 1:05 PM, Thijs Koerselman
<thijskoerselman@gmail.com> wrote:
> Thanks for the example, but I don't understand how it relates to my original
> question. I would like to define the plugin interface similar to a C++
> abstract base class.

Here's one solution to Lua abstract classes:

-- define a Base class
Base = {_abstract = {}}
Base.__index = Base

-- these 'methods' are abstract and any derived class must implement them
Base._abstract.one = true
Base._abstract.two = true

-- not abstract, will be inherited directly
function Base:three ()

end

function Base.check (object)
	-- is it derived from us?
	if not object._base == Base then
		return nil,"object is not derived from Base"
	end
	local mt = getmetatable(object)
	if not mt then
		return nil, "object does not have a metatable"
	end
	-- does it implement the required abstract methods?
	local abstract_members = Base._abstract
	for abstract in pairs(abstract_members) do
		if not mt[abstract] then
			return nil,"object does not implement "..abstract
		end
	end
	-- copy all non-abstract functions from Base into the derived class
       -- (being careful not to overwrite any overrides)
	for member,value in pairs(Base) do
		if not mt[member] then
			mt[member] = value
		end
	end
	return object
end


Derived = {_base = Base}
Derived.__index = Derived

function Derived.new ()
	return setmetatable({},Derived)
end

function Derived:one ()

end

function Derived:two () end

obj = Derived.new()
print(Base.check(obj))

Now, if you were to comment out the Derived:two function, then you
will see an appropriate error message.

A plugin file would probably look like this

-- plugin.lua -------------
require 'base'
module ('plugin',package.seeall)  -- for convenience

Derived = {_base = Base}
Derived.__index = Derived

function Derived:one () ... end

function Derived:two () ... end

return setmetatable({},Derived)
-----------------------------

Then you can do

obj,err = Base.check(require ('plugin'))

Obviously we can wrap this pattern so that some repeated code is factored out.

steve d.