Biblio::Doc::Article
que herede de la clase Biblio::Doc
descrita en la sección 6.4.
Ademas de los atributos de esta última, Biblio::Doc::Article
deberá tener
los atributos: journal
, volume
y pages
.
Procure que los métodos new
y AUTOLOAD
de la clase paterna sean suficientes (si es necesario reescribalos).
Para ello, declare en la nueva clase un hash con los atributos adicionales
journal
, volume
y pages
conteniendo los valores por defecto
y el modo de acceso (read/write
).
Algunas observaciones para escribir esta práctica con mas posibilidades de éxito:
El constructor new
en la clase Biblio::Doc
descrito en la sección 6.4 venía dado por:
1 sub new { 2 my $class = shift; 3 my $self = {}; 4 5 bless $self, ref($class) || $class; 6 7 $self->_incr_count(); 8 $self->_init(@_); 9 10 return $self; 11 }Observe que puesto que en la línea 5 se usa la versión de
bless
con dos argumentos, el objeto es bendecido en
la clase llamadora, de manera que una llamada a
Biblio::Doc::Article->new
produce un objeto de la
clase Biblio::Doc::Article
. Nótese también que en la llamada
de la línea 8, dado que $self
ya ha sido bendecido
en Biblio::Doc::Article
, la subrutina _init
que es llamada es, si existe, la de la clase Biblio::Doc::Article
.
Si no existe sería llamada la de Biblio::Doc
, la cual ha sido escrita como:
1 sub _init { 2 my ($self, %args) = @_; 3 my %inits; 4 my ($i, $j); 5 6 for $i ($self->_standard_keys) { 7 $j = $i; 8 $j =~ s/_//; 9 $inits{$i} = $args{$j} || $self->_default_for($i); 10 } 11 %$self = %inits; 12 }Esta subrutina confía en la llamada
$self->_standard_keys
para obtener las claves del objeto. Es posible entonces
escribir un método Biblio::Doc::Article::_standard_keys
el cual proporcione las claves nuevas junto con las que
produce el método equivalente en la clase padre
SUPER::_standard_keys
.
Esta estrategia es posible por que se envolvió la estructura de datos
%_defaults
my %_defaults = ( # Default Access _identifier => ["unknown",'read'], _author => ["unknown",'read/write'], _publisher => ["unknown",'read'], _title => ["unknown",'read'], _year => ["unknown",'read'], _url => ["unknown",'read/write'] );
con los métodos _standard_keys
y _default_for
.
Si en la línea 6 del código de _init
hubieramos escrito:
for $i (keys %_defaults)
la resolución del problema por delegación sería mas complicada.
Algo análogo
puede hacerse con la subrutina _default_for
.
De la misma forma, la función AUTOLOAD
de la clase Biblio::Doc
es:
1 sub AUTOLOAD { 2 no strict "refs"; 3 my $self = shift; 4 if (($AUTOLOAD =~ /\w+::\w+::get(_.*)/) && ($self->_accesible($1,'read'))) { 5 my $n = $1; 6 return unless exists $self->{$n}; 7 8 # Declarar el metodo get_***** 9 *{$AUTOLOAD} = sub { return $_[0]->{$n}; }; 10 11 return $self->{$n}; 12 } elsif (($AUTOLOAD =~ /\w+::\w+::set(_.*)/) && ($self->_accesible($1,'write'))) { 13 my $n = $1; 14 return unless exists $self->{$n}; 15 $self->{$n} = shift; 16 17 # Declarar el metodo set_***** 18 *{$AUTOLOAD} = sub { $_[0]->{$n} = $_[1]; }; 19 } else { 20 @_ = map { "\"".$_."\""; } @_; # Comillas a los argumentos... 21 print "Has llamado a $AUTOLOAD(",join(", ",@_),")\n"; 22 } 23 }Observe que la subrutina
_accesible
que es llamada en las líneas
4 y 12 es la de Biblio::Doc::Article
. Una buena estrategia al escribir
dicha rutina es usar delegación: Biblio::Doc::Article->_accesible
comprueba la accesibilidad de las claves del objeto que son específicas
de Biblio::Doc::Article
y delega en el método
SUPER::_accesible
para los restantes atributos.
Casiano Rodríguez León