Method::Lexical - private methods and lexical method overrides
package MyPragma;
use base qw(Method::Lexical);
sub import {
shift->SUPER::import(
'private' => sub { ... },
'UNIVERSAL::dump' => '+Data::Dump::pp'
)
}
#!/usr/bin/env perl
my $self = bless {};
{
use MyPragma;
$self->private(); # OK
$self->dump(); # OK
}
$self->private; # Can't locate object method "private" via package "main"
$self->dump; # Can't locate object method "dump" via package "main"
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 imported or declared.
The use Method::Lexical
statement takes a hashref or a list of key/value pairs in which the keys are method
names and the values are subroutine references or strings containing the name of the
method to be called. Unqualifed method names in keys are installed as methods in the currently-compiling package.
The following example summarizes the types of keys and values that can be supplied.
use Method::Lexical {
foo => \&foo, # unqualified method-name key: installed in the currently-compiling package e.g. main::foo
MyClass::foo => \&foo, # qualified method-name key: installed in the specified package
bar => sub { ... }, # anonymous sub value
baz => \&baz, # coderef value
quux => 'main::quux', # sub name value: unqualified names are resolved to the currently-compiling package
dump => '+Data::Dump::dump', # autoload Data::Dump
'UNIVERSAL::dump' => \&Data::Dump::dump, # define a universal method
'UNIVERSAL::isa' => \&my_isa, # override a universal method
'-autoload' => 1, # autoload modules for all subs passed by name
'-debug' => 1 # show diagnostic messages
};
Method::Lexical
options are prefixed with a hyphen to distinguish them from method names.
The following options are supported.
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 value
arguments with qualified names 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',
};
This option should not be confused with lexical AUTOLOAD methods, which are also supported e.g.
use Method::Lexical {
AUTOLOAD => sub { ... },
'UNIVERSAL::AUTOLOAD' => \&autoload,
};
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
};
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);
sub import { shift->SUPER::import('UNIVERSAL::dump' => '+Data::Dump::dump') }
1;
Client code can then import lexical methods from the module:
#!/usr/bin/env perl
use CGI;
{
use Universal::Dump;
say CGI->new->dump; # OK
}
eval { CGI->new->dump };
warn $@; # Can't locate object method "dump" via package "CGI"
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
}
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
}
Method calls on glob or filehandle invocants are interpreted as ordinary method calls.
The method resolution order for lexical method calls on pre-5.10 perls is currently fixed at depth-first search.
0.30
Copyright © 2009-2013 by chocolateboy.
This is free software; you can redistribute it and/or modify it under the terms of the Artistic License 2.0.