next up previous contents index practicapracticaPP2moodleLHPmoodlepserratacpanmodulospauseperlgoogleetsiiullpcgull
Sig: La notación SUPER Sup: Herencia Ant: Delegación en la Inicialización Err: Si hallas una errata ...

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 [14] 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.


next up previous contents index practicapracticaPP2moodleLHPmoodlepserratacpanmodulospauseperlgoogleetsiiullpcgull
Sig: La notación SUPER Sup: Herencia Ant: Delegación en la Inicialización Err: Si hallas una errata ...
Casiano Rodríguez León
2006-02-21