Diamantes

El método de delegación expuesto anteriormente falla si una clase hereda de un ancestro por dos caminos distintos (en la jerga esto se llama un diamante). En tal caso existe el riesgo de que una llamada por delegación a un _init de un antepasado se repita dos veces (una por cada camino hasta el antepasado) para el mismo objeto. Una solución es rastrear que inicializadores han sido visitados y evitar las subsiguientes visitas. Por ejemplo, si la clase C del ejemplo anterior es un candidato a inicializaciones repetidas (esto es, si puede ser la cúspide de un diamante), la podemos proteger usando el condicional que aparece en la línea 6 (Véase [18] para mas detalles):

 1  package C;
 2  @C::ISA = qw( _I B A);
 3  
 4  sub _init {
 5    my ($self, %args) = @_;
 6    return if $self->{_init}{__PACKAGE__}++;
 7    $self->A::_init(%args);
 8    $self->B::_init(%args);
 9    $self->{_c1} = $args{c1};
10  }
La macro __PACKAGE__ es igual al nombre del paquete actual (en este caso el paquete C). El uso de __PACKAGE__ puede ser de ayuda si por alguna razón decidimos copiar el código de _init en otro paquete: No tenemos que sustituir las apariciones de C por el nombre del nuevo paquete.

Una estrategia parecida puede aplicarse para evitar la llamada reiterada a destructores cuando se producen estructuras jerarquicas en diamante.

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