Perl Best Practices

16.9. Attribute Building

Have attributes initialized and verified automatically.

Most of the BUILD( ) methods shown so far in this chapter do nothing except initialize attributes with values extracted from the constructor's initializer hash. For example:

package Topping::Dessert; use Class::Std; {

# Attributes... my %name_of :ATTR; my %flavour_of :ATTR; sub BUILD { my ($self, $ident, $arg_ref) = @_; $name_of{$ident} = $arg_ref->{name}; $flavour_of{$ident} = $arg_ref->{flavour}; return; }

# etc.

Because this is such a common requirement, Class::Std provides a shortcut. When you declare an attribute using the :ATTR marker, you can specify the entry of the constructor's initialization hash that is to be used to initialize it. For example:

package Topping::Dessert; use Class::Std; {

# Attributes... my %name_of :ATTR( init_arg => 'name' ); my %flavour_of :ATTR( init_arg => 'flavour' );

# [No BUILD method required]

# etc.

This extra specification causes the new( ) method provided by Class::Std to automatically initialize those attributes with the correspondingly labeled values from the initialization hash it is passed.

More importantly, the approach also solves the problem of misspelled initializer labels (see "Base Class Initialization" earlier). When attributes are declared with :ATTR and an init_arg is specified, the Class::Std constructor will automatically throw an exception if the initialization hash doesn't contain a suitably named initialization value. For example, given the previous definition, a call like:

my $syrup = Topping::Dessert->new({ taste => 'Cocolicious', naem => 'UltraChoc' });

will throw the exception:

Missing initializer label for Topping::Dessert: 'name'. Missing initializer label for Topping::Dessert: 'flavour'. (Did you mislabel one of the args you passed: 'taste' or 'naem'?) Fatal error in constructor call at 'badnames.pl' line 22

Категории