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();