nysus has asked for the wisdom of the Perl Monks concerning the following question:
So what's wrong with this as a solution to prevent the autovivification of an object attribute? Is there a reason why something like this isn't offerred as a solution in Conway's book? To view the above code in its complete context with my additions in bold...if (%arg) { #performed only if obj. + arguments given my %_temp_hash = _return_attr_data(); #returns list + of obj. attributes foreach my $argcheck (keys %arg) { next if exists $_temp_hash{"_" . $argcheck}; #checks if + attribute exists croak "An invalid CD attribute given"; #if not, cro +aks with error } }
package Music; $VERSION = 1.00; use strict; use vars qw( $AUTOLOAD ); use Carp; { # Encapsulated class data my %_attr_data = # DEFAULT ACCESSIBILITY ( _name => [ '???', 'read'], _artist => [ '???', 'read'], _publisher => [ '???', 'read'], _ISBN => [ '???', 'read'], _tracks => [ '???', 'read'], _rating => [ -1, 'read/write'], _room => [ 'uncatalogued', 'read/write'], _shelf => [ "", 'read/write'], ); my $_count = 0; # Class methods, to operate on encapsulated class data # Is a specified object attribute accessible in a given mode sub _accessible { my ($self, $attr, $mode) = @_; $_attr_data{$attr}[1] =~ /$mode/ } # Classwide default value for a specified object attribute sub _default_for { my ($self, $attr) = @_; $_attr_data{$attr}[0]; } # List of names of all specified object attributes sub _standard_keys { keys %_attr_data; }
sub _return_attr_data { %_attr_data; }
# Retrieve object count sub get_count { $_count; } # Private count increment/decrement methods sub _incr_count { ++$_count } sub _decr_count { --$_count } } # Constructor may be called as a class method # (in which case it uses the calss's default values), # or an object method # (in which case it gets defaults from the existing object) sub new { my ($caller, %arg) = @_; my $caller_is_obj = ref($caller); my $class = $caller_is_obj || $caller; my $self = bless {}, $class;
if (%arg) { my %_temp_hash = _return_attr_data(); foreach my $argcheck (keys %arg) { next if exists $_temp_hash{"_" . $argcheck}; croak "An invalid CD attribute given"; } }
foreach my $attrname ( $self->_standard_keys() ) { my ($argname) = ($attrname =~ /^_(.*)/); if (exists $arg{$argname}) { $self->{$attrname} = $arg{$argname} } elsif ($caller_is_obj) { $self->{$attrname} = $caller->{$attrname} } else { $self->{$attrname} = $self->_default_for($attrname) } } $self->_incr_count(); return $self; } # Destructor adjusts class count sub DESTROY { $_[0]->_decr_count(); } # get or set room&shelf together sub get_location { ($_[0]->get_room(), $_[0]->get_shelf()) } sub set_location { my ($self, $room, $shelf) = @_; $self->set_room($room) if $room; $self->set_shelf($shelf) if $shelf; return; } # Implement other get_... and set_... methods (create as necessary) sub AUTOLOAD { no strict "refs"; my ($self, $newval) = @_; # Was it a get_... method? if ($AUTOLOAD =~ /.*::get(_\w+)/ && $self->_accessible($1, 'read') +) { my $attr_name = $1; *{$AUTOLOAD} = sub { return $_[0]->{$attr_name} }; return $self->{$attr_name}; } # Was it a set_... method? if ($AUTOLOAD =~ /.*::set(_\w+)/ && $self->_accessible($1, 'write' +)) { my $attr_name = $1; *{$AUTOLOAD} = sub { $_[0]->{$attr_name} = $_[1]; return }; $self->{$1} = $newval; return; } # Must have been a mistake then... croak "No such method: $AUTOLOAD"; } 1; # Ensure that the module can be succesfully use'd
$PM = "Perl Monk's";
$MCF = "Most Clueless Friar Abbot Bishop";
$nysus = $PM . $MCF;
Click here if you love Perl Monks
Edit: chipmunk 2001-007-15
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: Preventing autovivification of object attributes
by japhy (Canon) on Jul 15, 2001 at 22:26 UTC | |
by nysus (Parson) on Jul 15, 2001 at 22:56 UTC | |
by japhy (Canon) on Jul 15, 2001 at 22:59 UTC | |
|
Re: Preventing autovivification of object attributes
by bikeNomad (Priest) on Jul 16, 2001 at 00:49 UTC |