lua-users home
lua-l archive

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


On Wed, 2005-02-02 at 03:14, Mark Hamburg wrote:
> Lua actually has most of what one needs to build OOP systems -- particularly
> if one ignores encapsulation enforcement.


> One thing that might make that a little nicer syntactically would be if
> Lua's table constructors would recognize named functions and named methods

Aha. Good thinking.


> What is tricky are calls to the hidden methods.

Yes, but one can argue that this is very bad OO programming
anyhow. And indeed I have before and will again:

Most C++ textbooks incorrectly say virtual functions
should be public. This is just wrong, they should be
ultra-private because they're implementation details.

The *correct* way to factor your design is:

(a) public functions, always final, never call another
public function. Never call any private function.
These functions are effectively static global
functions which have protected access to the class.
They must enforce the precondition => postcondition
requirement but never have to worry about representation
invariants.

(b) protected functions. Can call protected and
private functions, always final, never call a public function.
Never use instance data.

(c) private functions. Only call private functions.
Can be overriden. Can access instance data.
Maintain representation invariants.

With this factoring, calling 'super' methods
is allowed, but is never difficult because they
cannot be overriden. In particular, only a protected
function f() ever needs to call a 'super' method,
and it will never be called f(), so there is no
need for the 'super' designation.

Since the protected 'super' methods are visible,
you know what their names are and just choose
distinct names in your subclass. Since the methods
are protected, it never impacts the public interface.

The technique above is the 'fully factored' technique,
typically you'd fudge it a bit to avoid triple
methods:

	class X {
		public final abs() { pr_abs(); }
		protected final pr_abs() { v_abs(); }
		private: virtual v_abs() { x = fabs(x); }
		float x;
	};
		
It is absolutely essential never to call a public
function from inside a class. The reason is that
public functions are expected to maintain class
invariants and have pre- and post-conditions,
and might check some of these things.

Often, inner calls don't need to maintain invariants,
and have stronger pre-conditions, eg you might
have an inner divide that assumes the dividend is
non-zero, but the public version can't assume that
and has to check.

More to the point, the non-overlappingness of
public function calls allows public calls to the
class to be instrumented inside the public functions,
this cannot work if they can call each other.

Anyhow, the point is that most OO people don't
really know how to do OO: there is no need to
support calling 'super' methods, because it
is a design fault in the first place.

> Hmmm... I'm sensing a set of minor proposals for enhancing Lua's OOP support
> here -- or rather Lua's support for building OOP implementations:

> 1. Some minor enhancements to table construction syntax for function-valued
> elements.

Yes, good work.

> 2. A way to duplicate functions so that the same function can be given
> different environments. (This might take the form of a general shallow-copy
> routine.)

Dubious :)

> 3. A __methods metatable. This would allow some errors to be caught earlier.
> It also makes it easier to implement property/attribute syntax support for
> objects without slowing down method dispatch.

Nice!


-- 
John Skaller, mailto:skaller@users.sf.net
voice: 061-2-9660-0850, 
snail: PO BOX 401 Glebe NSW 2037 Australia
Checkout the Felix programming language http://felix.sf.net