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
