Práctica: Herencia

Escriba una clase 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
Licencia de Creative Commons
Principios de Programación Imperativa, Funcional y Orientada a Objetos Una Introducción en Perl/Una Introducción a Perl
por Casiano Rodríguez León is licensed under a Creative Commons Reconocimiento 3.0 Unported License.

Permissions beyond the scope of this license may be available at http://campusvirtual.ull.es/ocw/course/view.php?id=43.
2012-06-19