lua-users home
lua-l archive

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


On 31/01/11 13:10, Steve Litt wrote:
[...]
> Speaking about what might replace it -- could something with callback 
> functions replace it?

I've found myself using interfaces more and more these days. I recently
wrote a big chunky widget library in C++ (ack, blech) which used
interfaces to allow me to refer to objects by function and not by type.

So, a widget actually implements EventListener (indicating it can be
sent any arbitrary event), RedrawEvent::Listener (indicating it supports
receiving unpacked redraw events), KeyEvent::Listener and
LayoutEvent::Listener likewise, Drawable (indicating it can be told to
draw itself onto a canvas), Geometrical (indicating it can be queried
for its size), Stringable (indicating it has text content that can be
queried or set), etc.

This means that I can write a bunch of generic algorithms that operate
on, say, Geometrical objects, and they don't care whether the object is
a widget or a lightweight rectangle or a heavyweight window.

It all works very nicely, and gives me the next best thing to duck
typing while still being type-safe.

In addition, most functionality is split off into multiple objects that
get piped together. I have a pick-up-and-throw list widget: this works
connecting together a DragBehaviour (which takes raw touch up/down
events and turns them into drag events with deltas) to a FlingBehaviour
(which takes drag events and turns them into move-to-offset events) to
the widget itself. The result is I end up with a single instance of the
Fling code which is decoupled from the List code.

In Lua this approach would be really easy, given its dynamic nature,
although you'd need a lot of discipline to avoid abusing it --- C++'s
type safety means that casting to an interface means prevents you from
accidentally call methods on the parent object when you're not supposed to.

Something like this to enforce the interfaces might be handy:

#if DEBUG
local function CastToGeometrical(o)
	local oo = {
		__index = oo,
		GetGeometry = function(self)
			return o:GetGeometry()
		end,
		SetGeometry = function(self, g)
			return o:SetGeometry(g)
		end
	}
	setmetatable(oo, oo)
	return oo
end
#else
local function CastToGeometrical(o)
	return o
end
#endif

function Widget:ResetGeometry(g)
	local g = CastToGeometrical(g)
	g:SetGeometry(Empty) -- works
	g:Redraw() -- produces run time error
end

-- 
┌─── dg@cowlark.com ───── http://www.cowlark.com ─────
│ "Thou who might be our Father, who perhaps may be in Heaven, hallowed
│ be Thy Name, if Name Thou hast and any desire to see it hallowed..."
│ --- _Creatures of Light and Darkness_, Roger Zelazny

Attachment: signature.asc
Description: OpenPGP digital signature