lua-users home
lua-l archive

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


2013/5/17 Rena <hyperhacker@gmail.com>:

> Lately I've been wishing for a simple "interface" functionality in Lua,
> where I could say "anything implementing 'foo' must have methods x, y and z"
> and perhaps provide default methods as well. But I haven't been able to come
> up with a syntax that isn't awkward and doesn't add overhead to every
> instantiation. For that matter since Lua is interpreted, any kind of
> interface system would add overhead to at least every time the module is
> loaded, which might be an issue for e.g. a web server; I wonder if there's a
> way to eliminate that overhead using luac...

Overheads are a price you pay when you need the protection and which you
save when you think you don't need it. I prefer to see what security I
am getting and to be aware of the price that I am paying for it, rather
than relying on some invisible ever-present kind.

So I like to see the mechanism, and don't mind expending a function call
on it. There are two mechanisms in Lua itself which I have used from
time to time, often both in one application, one for strict typing and
one for duck typing. They vary from application to application, but are
always something like this:

1. "is".

    function is(typ)
       return function(obj)
          return known[typ] and known[typ](obj)
              or (get(obj,'class') or type(obj)) == typ
       end
    end

    where 'known' is a table of functions that check types, and
    'get' is a generalization of 'rawget' that does not choke if
    called with a non-table.

    Usage for seldom-needed cases:
       is"thread"(obj)
    Usage for common cases:
       is_table = is"table" -- once
       is_table(obj)

2. "has".

   function has(methods)
      return function(obj)
         for method in methods:gmatch"[A-Za-z][A-Za-z0-9]*" do
            if not get(obj,method) then return false end
         end
         return true
      end
   end

   Usage for seldom-needed cases:
      has"assign,clear,new,delete"(obj)
   Usage for common cases:
      has"table"=has"concat,insert,remove,pack,unpack,sort" -- once
      has_table(obj)