package Simple;
use vars qw ($AUTOLOAD);
use Carp;
{
my $version = "1.0.0";
# object data
my %_attr_data =
(
"_debug" => [ 0, "r" ],
"_version" => [ $version, "r" ],
);
sub _accessible
{
my ($self, $attr, $mode) = @_;
$_attr_data{$attr}[1] =~ /$mode/
}
sub _default_for
{
my ($self, $attr) = @_;
$_attr_data{$attr}[0];
}
sub _standard_keys
{
keys %_attr_data;
}
sub new
{
my ($caller, %arg) = @_;
my $caller_is_obj = ref($caller);
my $class = $caller_is_obj || $caller;
my $self = bless {}, $class;
foreach my $membername ( $self->_standard_keys() )
{
my ($argname) = ($membername =~ /^_(.*)/);
if (exists $arg{$argname})
{ $self->{$membername} = $arg{$argname} }
elsif ($caller_is_obj)
{ $self->{$membername} = $caller->{$membername} }
else
{ $self->{$membername} = $self->_default_for($membername) }
}
return $self;
}
sub yip
{
my ($self) = @_;
print "yip!\n";
}
sub AUTOLOAD
{
no strict "refs";
my ($self, $newval) = @_;
if ($AUTOLOAD =~ /.*::get(_\w+)/ && $self->_accessible($1,'r'))
{
my $attr_name = $1;
*{$AUTOLOAD} = sub { return $_[0]->{$attr_name} };
return $self->{$attr_name}
}
if ($AUTOLOAD =~ /.*::set(_\w+)/ && $self->_accessible($1,'rw'))
{
my $attr_name = $1;
*{$AUTOLOAD} = sub { $_[0]->{$attr_name} = $_[1] };
$self->{$1} = $newval;
return
}
carp "no such method: $AUTOLOAD";
}
sub DESTROY
{
}
}
1;
####
package Simple::Child;
use Carp;
use lib ".";
use Simple;
@ISA = qw (Simple);
use vars qw ($AUTOLOAD);
{
my %_attr_data =
(
"_foo" => [ "bar", "rw" ],
);
sub _accessible
{
my ($self, $attr, $mode) = @_;
return $_attr_data{$attr}[1] =~ /$mode/ if exists $_attr_data{$attr};
return $self->SUPER::_accessible($attr,$mode);
}
sub _default_for
{
my ($self, $attr) = @_;
return $_attr_data{$attr}[0] if exists $_attr_data{$attr};
return $self->SUPER::_default_for($attr);
}
sub _standard_keys
{
my ($self) = @_;
($self->SUPER::_standard_keys(), keys %_attr_data);
}
sub yip
{
my ($self) = @_;
print "yip! yip!\n";
}
}
1;
####
#!/usr/bin/perl -w
use strict;
use lib ".";
use Simple::Child;
my $thingy = new Simple::Child;
print $thingy->get_foo . "\n" . $thingy->get_version . "\n";
$thingy->yip();