NAME
Class::Lego::Myself - Classes with a default object
SYNOPSIS
package My:Class;
use Class::Lego::Myself;
__PACKAGE__->give_my_self();
sub doit {
my $self = &find_my_self;
...
}
# somewhere else
$my = My::Class->new();
$my->doit(); # normal method call
#
My::Class->doit(); # doit() invoked over the default object
DESCRIPTION
This module is a minor helper to write OO modules with methods that work on some default object when called as class methods.
Suppose you're writing a nice OO module My::Class
with a handy method doit
. If customization is needed, the usage follows the example:
my $obj = My::Class->new( @new_args );
$obj->doit();
However, most of the time, your users will not be interested in the neat OO design underneath and some default object will be good enough. So a nice interface would be to use doit
as a class method too.
My::Class->doit();
# no need to create an instance
You may do that with this module. In two slightly different ways: (1) importing a helper function give_my_self
and (2) inheriting from it.
# importing &give_my_self
package My::Class;
use Class::Lego::Myself;
#use parent qw( Class::Lego::Myself ); # if you prefer IS-A relationship
__PACKAGE__->give_my_self();
After you called give_my_self
, your package is now endowed with a new sub find_my_self
which should be used in every method of the public interface intented to work both as an instance method and as a class method. So the first lines of doit
should look like this:
sub doit {
my $self = &find_my_self;
...
}
The task of find_my_self
is to bypass a reference if that's the invocant or to replace it with the default object as if
My::Class->doit();
were equivalent to
My::Class->get_default_object()->doit();
By default, the default object is constructed by $class->new
where $class
is the package over which give_my_self
was called.
The default object is always the same (that is, a singleton). The default object is not saved into a package variable or something like that. (Actually it resides in closures that make it accessible only to the code which needs it.) So it can't pollute your namespace and hopefully will keep us out of trouble with hard-to-track bugs.
- give_my_self
-
$package->give_my_self; $package->give_my_self({ default => $coderef, });
Install
find_my_self
into the receiver. The default object is computed once from the$coderef
given in the key'default'
of the hashref argument. The default$coderef
is:sub { $package->new() };
An explicit coderef may pass additional constructor arguments and do other things you want:
sub { $package->new(@customized_args); }
- find_my_self
-
my $self = &find_my_self; (my $self, @_) = &find_my_self; my ($self, @args) = &find_my_self;
This function examines the first argument and leaves it alone if it is a ref. Otherwise, replaces it with the corresponding default object (established when
give_my_self
was called). The first argument is shifted from the argument list.In scalar context, it returns the computed invocant. In list context, it returns the computed invocant and the the rest of the argument list.
The usage forms above are just handy ways to make current
@_
visible tofind_my_self
(as explained in perlsub). Otherwise, you could pass@_
explicitly but may need to update it.my $self = find_my_self(@_); # ok # but @_ is intact (including invocant)
CAVEATS
If you ask me, I may agree this module is possibly overkill. But better code is no code. And I don't have to code anymore to get methods which work seamlessly as class methods (with the right object behavior underneath).
HISTORY
I first borrowed the code of find_my_self
from Test::Base, but my use case turned to be pretty much simpler. Test::Base
struggles to turn methods into functions by discovering the default object under the hood. In contrast, this module is only for good OO code.
SEE ALSO
BUGS
Please report bugs via CPAN RT http://rt.cpan.org/NoAuth/Bugs.html?Dist=Class-Lego or mailto://bugs-Class-Lego@rt.cpan.org.
AUTHORS
Adriano R. Ferreira, <ferreira@cpan.org>
COPYRIGHT AND LICENSE
Copyright (C) 2008 by Adriano R. Ferreira
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.