INTRODUCTION
This is a bold attempt at getting a decent implementation for
interfaces in Perl.
Especially Perl 5.6.x.
I am aware of the presence of 'Class::Contract' and 'interface'. And
are particulary charmed by the ease-of-use of the latter. However it
lacks some insight. Thus I decided to write my own; largely based on
the principles of 'interfaces'
INSTALL
The usual.
% perl Makefile.PL
% make && make test
# make install
HOWTO
Read `perldoc lib/Interfaces.pm` first.
For a good example of how things work have a looksy through
test-lib/test.pl and test-lib/Car/*.pm
DESIGN DECISISIONS
* I choose not to use an import method (as does 'interfaces'). Mainly
because I wanted to be able to distinctly show others what they are
dealing with (An interface or an implementation). Second to that I
wanted to be able to create abstract interfaces within the same
code. Abstracts are interfaces 2.
* I've tried to use Devel::Size and PPI to do inspection of the
interfaces (and make sure that they are clean and
unimplemented). Devel::Size gave me deviation headache. It turns out
that the size of each method grows as the amount of methods
grow. I am no good with algoritms so finding the greater deviations
was left as an excercise for a later day.
PPI was just 2 much for such a little project.
I have made an implementation where I just run through the file
looking for clues. With enough satisfaction it will just accept.
* I mangle the namespaces of interfaces and implementers because I
want strict enforcement of the interface paradigm. I recognize
that this may lead to problems, but I have been careful.
HOW ITS DONE
interface() and abstract()
When calling the L<interface()> method the namespace of the caller
is checked against the syntax rules.
When all is well the namespace gets overwritten with an import
method. This will cause a die if anyone other then implementing
classes try to use it (actually proxied by the Interface class
itself). 'main' has been freed from this death - you might want to
print $VERSION and you should be able to.
Also it will publish a brand new method into the namespace of the
package it was called from, called '__get_interface_methods__'.
This returns all the available methods.
When the class is an abstract it will create a method with the
name '__get_abstract_methods__'. This will only give back the
abstractly defined methods.
The abstract method(s) of the abstract class will be overwritten
so that they die telling you that the method is abstract and
cannot be invoked here.
implements() and extends()
When calling either method each given interface is polled for
it's methods by calling '__get_xxx_methods__'. Then the caller is
checked for the methods using UNIVERSAL::can.
If all are present the @ISA of the caller is extended with the
name of the interface.
The methods that are missing are collected before confessing so
you can fix it all at once.
TODO
- Figure out a way to make interface / abstract inspection even better
- Make Interfaces.pm adhere to Perl::Critic a bit more