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