domingo, 16 de enero de 2011

Herencia con oracle 10g

Con Oracle 8, el entusiasmó de los objetos duró poco cuando comprobé que los TYPE OBJECT no soportaban la herencia y por supuesto el polimorfismo, realicé todo un trabajo embebiendo objetos padre dentro del hijo, de esta manera pude emular esta característica.

Acabo de realizar una reingeniería de mi proyecto, utilizando la verdadera herencia que esta versión ofrece (10g) y quiero compartir una de las características más importantes que pude utilizar, el polimorfismo.

Lo que encontraremos en esta entrada es un sencillo ejemplo de herencia, representado por tres objetos: padre, hijo1 e hijo2.

El type padre declara 3 atributos:
  • atributo1
  • atributo2
  • atributo3
Y declara dos métodos (no los implementa):
  • SetAtributo
  • Listar
Nuestros types hijos: hijo1, hijo2, cada uno mantendrá un atributo "propio":

El type hijo1 tiene 1 atributo propio (este type-clase hereda de padre)
  • ahijo1
E implementamos los métodos :
  • SetAtributo
  • Listar
El type hijo2 tiene 1 atributo propio (este type-clase hereda de padre)
  • ahijo2
E implementamos los métodos :
  • SetAtributo
  • Listar
Por favor observemos bien la implementación, que realiza cada tipo de método.

El código:

/* Declaración del TYPE padre, este tipo se crea con la característica NOT FINAL, para permitir ser utilizado como "padre" por otros types.

Tener en cuenta que los métodos no son implementados. */

CREATE OR REPLACE TYPE PADRE AS OBJECT (
atributo1 number(5),
atributo2 varchar2(10),
atributo3 date,
member procedure SetAtributo,
member procedure Listar
) not final
/

/* Creación de los tipos HIJO 1, HIJO 2. Estos TYPE heredan del tipo PADRE (UNDER PADRE). Cada tipo conserva un atributo propio (ahijo1, ahijo2), y lo más importante implementan los métodos SetAtributo y Listar. */

CREATE OR REPLACE TYPE HIJO1 UNDER PADRE (
ahijo1 number(5),
overriding member procedure SetAtributo,
overriding member procedure Listar,
member procedure Set1
)
/

CREATE OR REPLACE TYPE BODY HIJO1 IS

OVERRIDING MEMBER procedure SetAtributo IS
BEGIN
atributo1 := 1000;
atributo2 := 'HIJO 1';
atributo3 := sysdate-1000;
ahijo1 := 1553;
set1;
END SetAtributo;

OVERRIDING MEMBER procedure Listar IS
BEGIN
dbms_output.put_line(' Atributo 1 --> 'SELF.atributo1);
dbms_output.put_line(' Atributo 2--> 'SELF.atributo2);
dbms_output.put_line(' Por HIJO1 'SELF.ahijo1);
END Listar;

MEMBER procedure Set1 IS
BEGIN
atributo1 := 4567;
END Set1;

END;
/

CREATE OR REPLACE TYPE HIJO2 UNDER PADRE (
ahijo2 number(5),
overriding member procedure SetAtributo ,
overriding member procedure Listar
)
/

CREATE OR REPLACE TYPE BODY HIJO2 IS

OVERRIDING MEMBER procedure SetAtributo IS
BEGIN
atributo1 := 2000;
atributo2 := 'HIJO 2';
atributo3 := sysdate-2000;
ahijo2 := 9999;
END SetAtributo;

OVERRIDING MEMBER procedure Listar IS
BEGIN
dbms_output.put_line(' Atributo 1 --> 'SELF.atributo1);
dbms_output.put_line(' Atributo 2--> 'SELF.atributo2);
dbms_output.put_line(' Por HIJO2 'SELF.ahijo2);
END Listar;

END;
/

Fin del código que crea los tipos.

Veamos ahora el código para probar el polimorfismo

declare
v_padre padre;
v_hijo1 hijo1;
v_hijo2 hijo2;
begin
-- Inicializamos los hijos (hijo1, hijo2)
v_hijo1 := new hijo1(null,null,null,null);
v_hijo1.SetAtributo;
v_hijo2 := new hijo2(null,null,null,null);
v_hijo2.SetAtributo;

-- Instanciamos el padre con cada hijo y listamos valores.
v_padre := v_hijo1;
v_padre.Listar;
v_padre := v_hijo2;
v_padre.Listar;
end;

Quiero que antes de ejecutarlo, observemos bien el papel de este código:
  1. Se inicializan los objetos hijos, es decir, realizamos el llamado de los métodos SetAtributo tanto del hijo1 como del hijo2.
  2. Se Instancia al padre con el valor de cada objeto hijo, si señor, con el valor de cada objeto hijo, de esta manera este padre podra resolver los métodos de cada uno de sus hijos
Ejecutemos este ejemplo, una salida:

SQL> start probarpoli
Atributo 1 --> 4567 Atributo 2-->HIJO 1 Por HIJO1 Propio 1553
Atributo 1 --> 2000 Atributo 2-->HIJO 2 Por HIJO2 Propio 9999

Procedimiento PL/SQL terminado correctamente.

Quiero que detallen la forma en que podríamos encapsular el comportamiento de los métodos hijos, si son buenos observadores, se darán cuenta que estamos manipulando, desde el padre, atributos que pertenecen a diferentes hijos.
Bueno, este ejemplo aunque sencillo, muestra lo robusto que puede ser nuestro código con este paradigma asumido por PL/SQL.
__________________________________________________________________________________
"Llegar a viejo sin haberse enamorado de verdad..., es como no haber vivido"
Conoces a Joe Black

1 comentario: