NAME
Method::Lexical - private methods and lexical method overrides
SYNOPSIS
my $test = bless {};
$test->call_private(); # OK
$test->call_dump(); # OK
eval { $test->private() };
warn $@; # Can't locate object method "private" via package "main"
eval { $test->dump() };
warn $@; # Can't locate object method "dump" via package "main"
{
use feature qw(:5.10);
use Method::Lexical
private => sub { 'private' },
'UNIVERSAL::dump' => '+Data::Dump::dump'
;
sub call_private {
my $self = shift;
say $self->private();
}
sub call_dump {
my $self = shift;
say $self->dump();
}
}
DESCRIPTION
Method::Lexical
is a lexically-scoped pragma that implements lexical methods i.e. methods whose use is restricted to the lexical scope in which they are defined.
The use Method::Lexical
statement takes a list of key/value pairs in which the keys are method names and the values are subroutine references or strings containing the package-qualified name of the method to be called. The following example summarizes the type of keys and values that can be supplied.
use Method::Lexical
foo => sub { print "foo", $/ }, # anonymous sub value
bar => \&bar, # code ref value
new => 'main::new', # sub name value
dump => '+Data::Dump::dump', # autoload Data::Dump
'UNIVERSAL::dump' => \&Data::Dump::dump, # define an inherited method
'UNIVERSAL::isa' => \&my_isa, # override an inherited method
-autoload => 1, # autoload all subs passed by name
-debug => 1; # show diagnostic messages
OPTIONS
Method::Lexical
options are prefixed with a hyphen to distinguish them from method names. The following options are supported.
-autoload
If the value
is a string containing a package-qualified subroutine name, then the subroutine's module is automatically loaded. This can either be done on a per-method basis by prefixing the value
with a +
, or for all named value
arguments by supplying the -autoload
option with a true value e.g.
use Method::Lexical
foo => 'MyFoo::foo',
bar => 'MyBar::bar',
baz => 'MyBaz::baz',
-autoload => 1;
or
use MyFoo;
use MyBaz;
use Method::Lexical
foo => 'MyFoo::foo',
bar => '+MyBar::bar', # autoload MyBar
baz => 'MyBaz::baz';
-debug
A trace of the module's actions can be enabled or disabled lexically by supplying the -debug
option with a true or false value. The trace is printed to STDERR.
e.g.
use Method::Lexical
foo => \&foo,
bar => sub { ... },
-debug => 1;
METHODS
import
Method::Lexical::import
can be called indirectly via use Method::Lexical
or can be overridden by subclasses to create lexically-scoped pragmas that export methods whose use is restricted to the calling scope e.g.
package Universal::Dump;
use base qw(Method::Lexical);
use Data::Dump qw(dump);
sub import { shift->SUPER::import('UNIVERSAL::dump' => \&dump) }
1;
Client code can then import lexical methods from the module:
#!/usr/bin/env perl
use feature qw(:5.10);
use FileHandle;
{
use Universal::Dump;
say FileHandle->new->dump; # OK
}
eval { FileHandle->new->dump };
warn $@; # Can't locate object method "dump" via package "FileHandle"
unimport
Method::Lexical::unimport
removes the specified lexical methods from the current scope, or all lexical methods if no arguments are supplied.
use Method::Lexical foo => \&foo;
my $self = bless {};
{
use Method::Lexical
bar => sub { ... },
'UNIVERSAL::baz' => sub { ... };
$self->foo(); # OK
$self->bar(); # OK
$self->baz(); # OK
no Method::Lexical qw(foo);
eval { $self->foo() };
warn $@; # Can't locate object method "foo" via package "main"
$self->bar(); # OK
$self->baz(); # OK
no Method::Lexical;
eval { $self->bar() };
warn $@; # Can't locate object method "bar" via package "main"
eval { $self->baz() };
warn $@; # Can't locate object method "baz" via package "main"
}
$self->foo(); # OK
Unimports are specific to the class supplied in the no
statement, so pragmas that subclass Method::Lexical
inherit an unimport
method that only removes the methods they installed e.g.
{
use MyPragma qw(foo bar baz);
use Method::Lexical quux => \&quux;
$self->foo(); # OK
$self->quux(); # OK
no MyPragma qw(foo); # unimports foo
no MyPragma; # unimports bar and baz
no Method::Lexical; # unimports quux
}
CAVEATS
Lexical methods must be defined before any invocations of those methods are compiled, otherwise those invocations will be compiled as ordinary method calls. This won't work:
sub public {
my $self = shift;
$self->private(); # not a private method; compiled as an ordinary (public) method call
}
use Method::Lexical private => sub { ... };
This works:
use Method::Lexical private => sub { ... };
sub public {
my $self = shift;
$self->private(); # OK
}
Calls to fully-qualified method names are compiled and interpreted as as normal (i.e. public) method calls. So the following are not called as lexical methods:
my $method = 'Foo::Bar::baz';
$self->Foo::Bar::baz();
$self->SUPER::foo();
$self->$method();
Likewise, method calls on glob or filehandle invocants are interpreted as ordinary method calls.
VERSION
0.03
SEE ALSO
AUTHOR
chocolateboy <chocolate@cpan.org>
COPYRIGHT AND LICENSE
Copyright (C) 2009 by chocolateboy
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.8.8 or, at your option, any later version of Perl 5 you may have available.