lunes, 12 de diciembre de 2016

Sobrecargas en Oracle

Objetivos:
• Introducción al concepto de Polimorfismo.
• Describir las Sobrecargas.
---Sus Ventajas.
---Su Implementación.

________________________________________________________________________________
El Polimorfismo
En programación orientada a objetos, el Polimorfismo se refiere a la propiedad que permite enviar mensajes sintácticamente iguales a objetos de tipos distintos. El único requisito que deben cumplir los objetos que se utilizan de manera polimórfica es saber responder al mensaje que se les envía.[1]

La definición de diccionario de Polimorfismo se refiere a un principio en biología en el cual un organismo o especie puede tener diferentes formas o etapas. Este principio también puede aplicarse a la programación orientada a objetos en lenguajes como Java. Las subclases de una clase pueden definir sus propios comportamientos únicos y compartir algunas de las funcionalidades de la clase padre.[2]

En síntesis, el Polimorfismo es una característica de la programación orientada a objetos, la cual provee la capacidad de crear una variable, una función o un objeto que tiene más de una forma.

En la programación de procedimiento de Oracle(PL/SQL), también es posible usar el concepto de Polimorfismo en forma de Sobrecarga.
____________________________________________________________________________________
Las Sobrecargas
El termino Sobrecarga se refiere a la capacidad de utilizar un solo identificador para definir múltiples métodos de una clase que difieren en sus parámetros de entrada y salida. Los métodos sobrecargados se usan generalmente cuando conceptualmente ejecutan la misma tarea pero con un conjunto de parámetros ligeramente diferente.

La Sobrecarga es un concepto utilizado para evitar código redundante donde el mismo nombre de método se utiliza varias veces, pero con un conjunto diferente de parámetros. El método en cuestión  que es llamado durante el tiempo de ejecución es resuelto en tiempo de compilación, evitando así errores en tiempo de ejecución. La sobrecarga proporciona claridad de código, elimina la complejidad y mejora el rendimiento en tiempo de ejecución.[3]

Las Sobrecargas en PL/SQL Oracle
PL/SQL permite sobrecargar nombres de Subprogramas(Funciones y Procedimientos) y Métodos de Tipo Objeto. Es decir, puede utilizar el mismo nombre para varios subprogramas diferentes, siempre y cuando sus parámetros formales difieran en número, orden o familia de tipo de dato.

Esto es, puede colocar los dos procedimientos llamados pro_prueba(que difieran en sus parámetros) en el mismo Bloque Anónimo, Subprograma, Paquete o Tipo de Objeto. Luego PL/SQL determina qué procedimiento llamar mediante la verificación de sus parámetros formales.

Algunas Directrices:
• Sólo es posible sobrecargar subprogramas locales, osea, esos que están contenidos en otros subprogramas. No puede sobrecargar subprogramas autónomos.

• No puede sobrecargar dos subprogramas si sus parámetros formales difieren sólo en nombre o modo(IN, OUT).

• No puede sobrecargar subprogramas cuyos parámetros difieren sólo en Subtipo. Por ejemplo, un procedimiento que acepta un parámetro INTEGER y el otro un REAL, esto porque INTEGER REAL son ambos Subtipos de NUMBER y por lo tanto están en la misma familia. Nota: Lo mismo aplica para VARCHAR2VARCHAR CHAR.

• No puede sobrecargar dos funciones que difieren sólo en el tipo de datos del valor de retorno, incluso si los tipos están en familias diferentes. Por ejemplo, no se puede sobrecargar dos funciones donde una retorne BOOLEAN y la otra INTEGER.
____________________________________________________________________________________
Ejemplos:

SET SERVEROUTPUT ON
DECLARE
        PROCEDURE pro_sobrecarga IS
        BEGIN
            DBMS_OUTPUT.PUT_LINE('pro_sobrecarga: no recibe parámetros');
        END pro_sobrecarga;
--
        PROCEDURE pro_sobrecarga(p_num NUMBERIS
        BEGIN
            DBMS_OUTPUT.PUT_LINE('pro_sobrecarga: recibe 1 parámetro');
        END pro_sobrecarga;
--
        PROCEDURE pro_sobrecarga(p_num NUMBER, p_var VARCHAR2IS
        BEGIN
            DBMS_OUTPUT.PUT_LINE('pro_sobrecarga: recibe 2 parámetros');
        END pro_sobrecarga;
BEGIN
    pro_sobrecarga;
    pro_sobrecarga(NULL,NULL);
    pro_sobrecarga(NULL);
END;
/*Este ejemplo ejemplo muestra con simplicidad como funcionan las Sobrecargas en Oracle. Notar que cada sobrecarga imprime una cadena distinta y que al momento de llamarlas no hay necesidad de validar cual de ellas invocar, Oracle hace ese trabajo internamente.*/
---OUTPUT:
---
CREATE OR REPLACE PACKAGE pkg_sobrecarga IS
    FUNCTION func_letras_numeros(p_param NUMBER)
        RETURN VARCHAR2;

    FUNCTION func_letras_numeros(p_param VARCHAR2)
        RETURN VARCHAR2;
END;
/
/**/
---
CREATE OR REPLACE PACKAGE BODY pkg_sobrecarga IS
    FUNCTION func_letras_numeros(p_param NUMBER)
        RETURN VARCHAR2 IS
        v_param_length  NUMBER;
        v_msg           VARCHAR2(500);
        v_type          VARCHAR2(50);
     BEGIN
        v_param_length  :=  LENGTH(p_param);
        v_type          :=
                         CASE
                            WHEN v_param_length<2 THEN 'un dígito.'
                            ELSE v_param_length||' dígitos.'
                         END;
        v_msg           :=  ', Tipo: Numérico, con una dimensión de '||v_type;

        RETURN p_param||v_msg;
     END func_letras_numeros;
--
    FUNCTION func_letras_numeros(p_param VARCHAR2)
        RETURN VARCHAR2 IS
        v_param_length  NUMBER;
        v_msg           VARCHAR2(500);
        v_type          VARCHAR2(50);
     BEGIN
        v_param_length  := LENGTH(p_param);
        v_type          :=
                         CASE
                            WHEN v_param_length<2 THEN 'un carácter.'
                            ELSE v_param_length||' Caracteres.'
                         END;
        v_msg           := ', Tipo: Carácter, con una dimensión de '||v_type;

        RETURN p_param||v_msg;
     END func_letras_numeros;
END pkg_sobrecarga;
/
/**/
---
SELECT
        pkg_sobrecarga.func_letras_numeros(5) AS "Resultado 1",
        pkg_sobrecarga.func_letras_numeros('a'AS "Resultado 2",
        pkg_sobrecarga.func_letras_numeros(5000AS "Resultado 3",
        pkg_sobrecarga.func_letras_numeros('MAGIC PL/SQL'AS "Resultado 4"
FROM dual;
/**/
---OUTPUT:

CREATE OR REPLACE TYPE typ_sobrecarga IS OBJECT
(
    col_id          NUMBER,
    col_name        VARCHAR2(25),
    col_date        DATE,
    input_method    VARCHAR2(26),

    CONSTRUCTOR FUNCTION typ_sobrecarga RETURN SELF AS RESULT,
    CONSTRUCTOR FUNCTION typ_sobrecarga(p_param VARCHAR2) RETURN SELF AS RESULT
);
/
/*En este ejemplo definimos la especificación del tipo de objeto: typ_sobrecarga el cual tiene 4 atributos y dos sobrecargas del CONSTRUCTOR.*/
---
CREATE OR REPLACE TYPE BODY typ_sobrecarga IS

    CONSTRUCTOR FUNCTION typ_sobrecarga
                RETURN SELF AS RESULT IS
    BEGIN
        SELF.col_id         :=  1456;
        SELF.col_name       :=  'Hola Mundo!!!';
        SELF.col_date       :=  ADD_MONTHS(SYSDATE,5);
        SELF.input_method   :=  'CONSTRUCTOR sin Parámetros';

        RETURN;
    END typ_sobrecarga;

    CONSTRUCTOR FUNCTION typ_sobrecarga(p_param VARCHAR2)
                RETURN SELF AS RESULT IS
    
    BEGIN
        SELF.col_id         :=  TO_NUMBER(p_param);
        SELF.col_name       :=  'Hola Pueblo!!!';
        SELF.col_date       :=  ADD_MONTHS(SYSDATE,-2);
        SELF.input_method   :=  'CONSTRUCTOR 1 Parámetro';

        RETURN;

        EXCEPTION
            WHEN OTHERS THEN
                SELF.col_id         :=  2589;
                SELF.col_name       :=  p_param;
                SELF.col_date       :=  ADD_MONTHS(SYSDATE,-2);
                SELF.input_method   :=  'CONSTRUCTOR 1 Parámetro';

                RETURN;
    END typ_sobrecarga;
END;
/
/*Aquí tenemos el cuerpo del objeto antes definido; Notar que la primera sobrecarga del CONSTRUCTOR que no recibe parámetros inicializa los atributos con valores por defecto; La segunda sobrecarga que recibe un parámetro usa ese parámetro para inicializar el atributo col_id o col_name dependiendo que tipo de parámetro recibido. Tenga en cuenta que aun es posible usar el CONSTRUCTOR original que recibe un parámetro por cada atributo.*/
---
SET SERVEROUTPUT ON
DECLARE
    v_testing   typ_sobrecarga;
BEGIN
    v_testing   :=  typ_sobrecarga;

    DBMS_OUTPUT.PUT_LINE
                        (
                            v_testing.col_id||CHR(10)||
                            v_testing.col_name||CHR(10)||
                            v_testing.col_date||CHR(10)||
                            v_testing.input_method
                        );
END;
/
/*En este SCRIPT implementamos el objeto: typ_sobrecarga; Notar en el OUTPUT los diferentes resultados dependiendo cual sobrecarga se ejecute.*/
---OUTPUT:

____________________________________________________________________________________
Fuentes: https://docs.oracle.com/cd/A97630_01/appdev.920/a96624/08_subs.htm#12353