- , - - globs. .
, , .
package WeirdClass;
sub new {
my ($class, $name, $code) = @_;
if ($name) {
no strict;
*{__PACKAGE__ . "::$name"} = $code;
}
bless {} => $class;
}
:
my $object = WeirdClass->new(foo => sub {say "foo"});
$object->foo();
:
my $another_object = WeirdClass->new();
$another_object->foo;
, :
package BetterClass;
sub new {
my ($class, %args) = @_;
bless \%args => $class;
}
sub DESTROY {};
sub AUTOLOAD {
my $self = shift;
(my $method = our $AUTOLOAD) =~ s/.*://;
die "forbidden method $method" unless $self->{can}{$method};
given ($method) {
say "foo" when "foo";
say "bar" when "bar";
when ("add") {
my ($x, $y) = @_;
return $x + $y;
}
default { die "unknown method $method" }
}
}
:
my $o = BetterClass->new(can => { foo => 1, bar => 0});
$o->foo;
my $p = BetterClass->new(can => {bar => 1, add => 1});
$p->bar;
say $p->add(5, 6);
, .
: can()
AUTOLOAD can, :
my %methods;
BEGIN {
%methods = (
foo => sub {say "foo"},
bar => sub {say "bar"},
add => sub {
my ($self, $x, $y) = @_;
$x + $y;
},
);
}
can:
my $orig_can;
BEGIN{ $orig_can = __PACKAGE__->can("can") }
sub can {
my ($self, $meth) = @_;
my $code = $methods{$meth} if ref $self and $self->{can}{$meth};
return $code if $code;
return $self->$orig_can($meth);
}
AUTOLOAD
my ($self) = @_;
(my $method = our $AUTOLOAD) =~ s/.*://;
my $code = $self->can($method) or die "unknown method $method";
goto &$code;