miércoles, 18 de mayo de 2011

practica 1(polimorfismo)



Polimorfismo

El concepto de Polimorfismo es uno de los fundamentos para cualquier lenguaje orientado a Objetos, las mismas raíces de la palabra pueden ser una fuerte pista de su significado: Poli = Multiple, morfismo= Formas , esto implica que un mismo Objeto puede tomar diversas formas.
El poder manipular un Objeto como si éste fuera de un tipo genérico otorga mayor flexibilidad al momento de programar con Objetos, el término Polimorfismo también es asociado con un concepto llamado Late-Binding (Ligamiento Tardío),
EJEMPLO:
import java.util.*;

class Instrumento {
    public void tocar() {
 System.out.println("Instrumento.tocar()");
    }
    public String tipo() {
 return "Instrumento";
    }
    public void afinar() {}
}

class Guitarra extends Instrumento {
    public void tocar() {
 System.out.println("Guitarra.tocar()");
    }
    public String tipo() { return "Guitarra"; }
    public void afinar() {}
}

class Piano extends Instrumento {
    public void tocar() {
 System.out.println("Piano.tocar()");
    }
    public String tipo() { return "Piano"; }
    public void afinar() {}
}

class Saxofon extends Instrumento {
    public void tocar() {
 System.out.println("Saxofon.tocar()");
    }
    public String tipo() { return "Saxofon"; }
    public void afinar() {}
}

// Un tipo de Guitarra 
class Guzla extends Guitarra {
       public void tocar() {
         System.out.println("Guzla.tocar()");
       }
       public void afinar() {
         System.out.println("Guzla.afinar()");
       }
     }

// Un tipo de Guitarra 
class Ukelele extends Guitarra {
    public void tocar() {
 System.out.println("Ukelele.tocar()");
    }
    public String tipo() { return "Ukelele"; }
}

public class Musica {

    // No importa el tipo de Instrumento,
    // seguirá funcionando debido a Polimorfismo:
    static void afinar(Instrumento i) {
 // ...
 i.tocar();
    }

    static void afinarTodo(Instrumento[] e) {
 
 for(int i = 0; i < e.length; i++)
     afinar(e[i]);
    }


    public static void main(String[] args) {
 Instrumento[] orquesta = new Instrumento[5];
 int i = 0;
 // Up-casting al asignarse el Arreglo
 orquesta[i++] = new Guitarra();
 orquesta[i++] = new Piano();
 orquesta[i++] = new Saxofon();
 orquesta[i++] = new Guzla();
 orquesta[i++] = new Ukelele();
 afinarTodo(orquesta);
    }
} 
 
Clase Musica


En el código fuente de Musica.java son diseñadas diversas Clases que demuestran el uso de Polimorfismo:
  • Instrumento: Es utilizada como la Clase Base para el resto de Clases y en ella son definidos tres métodos: tocar,tipo y afinar.
  • Guitarra: Hereda ("Inherit") de la Clase Instrumento y redefine ("Override") los métodos de ésta.
  • Piano: Hereda ("Inherit") de la Clase Instrumento y redefine ("Override") los métodos de ésta.
  • Saxofon: Hereda ("Inherit") de la Clase Instrumento y redefine ("Override") los métodos de ésta.
  • Guzla: Hereda ("Inherit") de la Clase Guitarra y redefine ("Override") los métodos de ésta.
  • Ukelele: Hereda ("Inherit") de la Clase Guitarra y redefine ("Override") los métodos de ésta.
Las definiciones de la Clase principal Musica son descritas en los siguientes incisos:
  • El primer método definido en esta Clase llamado afinar toma como valor de entrada una referencia del tipo Instrumento, sobre la cual es invocado el método tocar.
  • Un segundo método nombrado afinarTodo toma como valor de inicia un arreglo de Instrumento, el cual es procesado por un ciclo que a su vez manda llamar el método afinar con los respectivos valores del arreglo.
  • Dentro del método principal se define lo siguiente:
    • Primeramente se genera un arreglo de Instrumento para 5 Objetos.
    • Se inicializa un primitivo i con un valor de cero.
    • A través de la referencia orquesta son asignados distintos Objetos al arreglo, nótese que aunque el arreglo es de tipo Instrumento es posible asignar los Objetos: Guitarra,Piano,Saxofon,Guzla,Ukelele.
    • Finalmente se invoca el método afinarTodo con la referencia que representa el arreglo de Instrumento.
Al ser ejecutado este programa se obtienen los siguientes resultados:
$ java Musica
Guitarra.tocar()
Piano.tocar()
Saxofon.tocar()
Guzla.tocar()
Ukelele.tocar()
 

Herencias Múltiples

Herencia múltiple: una clase puede heredar características de una o más clases, por lo tanto, puede tener varios padres.
ejemplo:


import java.util.*;


interface PuedeCurar { 
    void curar();
}

interface PuedeConsultar { 
    void consultar();
} 

interface PuedeRecetar{ 
    void recetar();
}

class Cirujano { 
    public void operar() { System.out.println("Cirujano.operar()"); } 
} 

class Medico extends Cirujano
    implements PuedeCurar, PuedeConsultar, PuedeRecetar { 
    public void curar() { System.out.println("Medico.curar()"); } 
    public void consultar() { System.out.println("Medico.consultar()"); } 
    public void recetar() { System.out.println("Medico.recetar()"); } 
}

class Cardiologo { 
    static void r(PuedeCurar x) { x.curar(); }
    static void s(PuedeConsultar x) { x.consultar(); } 
    static void t(PuedeRecetar x) { x.recetar(); } 
    static void u(Cirujano x) { x.operar(); } 
 
   public static void main(String[] args) {
 Medico m = new Medico();
 r(m); 
 s(m); 
 t(m); 
 u(m); 
    }
}
 
 

Interfases PuedeCurar,PuedeConsultar,PuedeRecetar.

Cada una de estas interfases define un método el cual deberá ser implementado en las respectivas Clases que hagan uso de las interfases.

Clase Cirujano.

Esta Clase simplemente define un método llamado operar que imprime un mensaje a pantalla.

Clase Medico.

Contiene la mayor parte de código funcional de este archivo fuente:
  • Es definida al igual que cualquier otra Clase con el vocablo class.
  • Se utiliza el vocablo extends para heredar ("Inherit") el comportamiento de la Clase Cirujano.
  • Seguido se implementan las interfases PuedeCurar,PuedeConsultar,PuedeRecetar a través de implements, esto obliga a que sean definidos los métodos de las diversas interfases.
  • Son escritas las diversas implementaciones de los métodos de cada interfase, los cuales envían un mensaje a pantalla.

    Clase Cardiologo.

  • Dentro del método principal (main) de esta Clase se genera una instancia de la Clase Medico.
  • A través de dicha referencia son invocados los diversos métodos locales r,s,t,u.
  • El método r manda llamar la función curar, nótese que aunque el dato de entrada aparece como PuedeCurar (Interfase) la invocación se lleva acabo directamente de la Clase Medico.
  • El método s manda llamar la función consultar, nótese que aunque el dato de entrada aparece como PuedeConsultar (Interfase) la invocación se lleva acabo directamente de la Clase Medico.
  • El método t manda llamar la función recetar, nótese que aunque el dato de entrada aparece como PuedeRecetar (Interfase) la invocación se lleva acabo directamente de la Clase Medico.
  • El método u invoca la función operar disponible en la Clase Cirujano.


 
 
 

Interfases

Una Interfase es una Clase abstracta llevada al extremo, la cual permite pre-definir el uso de métodos/campos en futuras clases tal como: Una jerarquía de Instrumentos restringido al uso de una Interfase Instrumento, o bien, una estructura de Figuras al uso de la Interfase Figura.
Una Interfase básicamente dice: "Todas las Clases que implementen esta Interfase deben contener su misma estructura", para definir una Interfase se utiliza el vocablo interface y para especificar que una Clase debe utilizar determinada Interfase se utiliza el vocablo implements.

Una característica especifica de Interfases que no es posible a través de Clases Abstractas es el uso de Herencias Múltiples ("Multiple Inheritance"), este concepto reside en diseñar Clases que adoptan el comportamiento de más de una Clase

ejemplo:


import java.util.*;

interface Instrumento {
    // Constante al compilar, automáticamente static y final 
    int i = 5;
    // Métodos Automáticamente Públicos 
    void tocar();
    String tipo();
    void afinar();
}

class Guitarra implements Instrumento {
    public void tocar() {
 System.out.println("Guitarra.tocar()");
    }
    public String tipo() { return "Guitarra"; }
    public void afinar() {}
}

class Piano implements Instrumento {
    public void tocar() {
 System.out.println("Piano.tocar()");
    }
    public String tipo() { return "Piano"; }
    public void afinar() {}
}

class Saxofon implements Instrumento {
    public void tocar() {
 System.out.println("Saxofon.tocar()");
    }
    public String tipo() { return "Saxofon"; }
    public void afinar() {}
}

// Un tipo de Guitarra 
class Guzla extends Guitarra {
       public void tocar() {
         System.out.println("Guzla.tocar()");
       }
       public void afinar() {
         System.out.println("Guzla.afinar()");
       }
     }

// Un tipo de Guitarra 
class Ukelele extends Guitarra {
    public void tocar() {
 System.out.println("Ukelele.tocar()");
    }
    public String tipo() { return "Ukelele"; }
}

public class Musica3 {

    // No importa el tipo de Instrumento,
    // seguirá funcionando debido a Polimorfismo:
    static void afinar(Instrumento i) {
 // ...
 i.tocar();
    }

    static void afinarTodo(Instrumento[] e) {
 
 for(int i = 0; i < e.length; i++)
     afinar(e[i]);
    }


    public static void main(String[] args) {
        // Declarar un Arreglo SIN INSTANCIAS es válido en Clases Abstractas
 Instrumento[] orquesta = new Instrumento[5];
 int i = 0;
 // Up-casting al asignarse el Arreglo
 orquesta[i++] = new Guitarra();
 orquesta[i++] = new Piano();
 orquesta[i++] = new Saxofon();
 orquesta[i++] = new Guzla();
 orquesta[i++] = new Ukelele();
 afinarTodo(orquesta);
    }
}

Clases Abstractas.

Al ser utilizado Herencias ("Inheritance") y/o Polimorfismo es muy común que en la Clase Base existan métodos diseñados únicamente con el propósito de ofrecer una guia para las Clases heredadas, en Java existe un vocablo que permite prohibir el uso de métodos en Clases Base, este calificativo es : abstract.Al ser definido un método como abstract se restringe que éste sea llamado directamente, cuando una Clase contiene un método de este tipo a ésta se le llama: Clase Abstracta.
Al ser definida una Clase, además de ser declarados los métodos/campos como abstract también es necesario utilizar el vocablo abstract en la definición de cada Clase.
Una de las características de las Clases que Heredan("Inherit") de una Clase abstracta, es que éstas deben definir los mismos métodos definidos en la Clase Base; en Java existe otro mecanismo que permite llevar acabo diseños donde se parte de una Estructura o Cápsula.
ejemplo

import java.util.*;

abstract class Instrumento {
    public abstract void tocar();
    public String tipo() {
 return "Instrumento";
    }
    public abstract void afinar();
}

class Guitarra extends Instrumento {
    public void tocar() {
 System.out.println("Guitarra.tocar()");
    }
    public String tipo() { return "Guitarra"; }
    public void afinar() {}
}

class Piano extends Instrumento {
    public void tocar() {
 System.out.println("Piano.tocar()");
    }
    public String tipo() { return "Piano"; }
    public void afinar() {}
}

class Saxofon extends Instrumento {
    public void tocar() {
 System.out.println("Saxofon.tocar()");
    }
    public String tipo() { return "Saxofon"; }
    public void afinar() {}
}

// Un tipo de Guitarra 
class Guzla extends Guitarra {
       public void tocar() {
         System.out.println("Guzla.tocar()");
       }
       public void afinar() {
         System.out.println("Guzla.afinar()");
       }
     }

// Un tipo de Guitarra 
class Ukelele extends Guitarra {
    public void tocar() {
 System.out.println("Ukelele.tocar()");
    }
    public String tipo() { return "Ukelele"; }
}

public class Musica2 {

    // No importa el tipo de Instrumento,
    // seguirá funcionando debido a Polimorfismo:
    static void afinar(Instrumento i) {
 // ...
 i.tocar();
    }

    static void afinarTodo(Instrumento[] e) {
 
 for(int i = 0; i < e.length; i++)
     afinar(e[i]);
    }


    public static void main(String[] args) {
        // Declarar un Arreglo SIN INSTANCIAS es valido en Clases Abstractas
 Instrumento[] orquesta = new Instrumento[5];
        // Generar una INSTANCIA de una la Clase Abstracta no es valido 
        // Instrumento nuevo = new Instrumento();
 int i = 0;
 // Up-casting al asignarse el Arreglo
 orquesta[i++] = new Guitarra();
 orquesta[i++] = new Piano();
 orquesta[i++] = new Saxofon();
 orquesta[i++] = new Guzla();
 orquesta[i++] = new Ukelele();
 afinarTodo(orquesta);
    }
}