martes, 18 de octubre de 2011

Conceptos Basicos de POO

La programación orientada a objetos, se define como un paradigma que permite realizar una abstracción de la realidad que se puede implementar en una aplicación de software con el fin de resolver problemas mediante el uso de un lenguaje de programación.

El paradigma de orientación a objetos comprende una gran cantidad de conceptos que permiten el desarrollo de aplicaciones robustas.

Paquete

Un paquete es un contenedor de clases. Se utiliza para ordenar el código de forma consistente de acuerdo a los servicios implementados. Para que un código se encuentre contenido en un paquete es necesario agregar la siguiente sentencia.

package MiPaquete;

En donde “MiPaquete” es el nombre del paquete que contendrá el código. Por otro lado, si se desea hacer uso de servicios implementados en otros paquetes se debe agregar el siguiente código.

import OtroPaquete;

Java contiene una gran cantidad de paquetes que proveen una gran cantidad de servicios. Algunos de estos paquetes se presentan en la siguiente tabla.

Paquete Descripción
java.appletProvee clases necesarias para crear applets.
java.awtContiene todas las clases para crear interfaces para pintar graficas e imágenes.
java.awt.colorProvee clases para definiciones de color.
java.awt.eventProvee interfaces y clases para manejar eventos de componentes gráficos.
java.awt.fontProvee interfaces y clases relacionadas con fuentes.
java.awt.geomProvee clases 2D para definir operaciones relacionadas con geometría
de dos dimensiones.
java.awt.imageProvee interfaces y clases para crear y modificar imágenes.
java.awt.printProvee interfaces y clases para usar el API de impresión.
java.beansProvee interfaces y clases para el desarrollo de beans que hace referencia a
componentes basados en JavaBeansTM architecture.
java.ioProvee interfaces y clases para entrada y salida de datos serializables.
java.langProvee clases fundamentales para el diseño del lenguaje de
programación Java.
java.mathProvee clases para optimizar la precisión de entero aritmético
(BigInteger) decimal aritmético (BigDecimal).
java.netProvee clases para implementar aplicaciones de red.
java.rmiProvee interfaces y clases para servicios RMI.
java.securityProvee interfaces y clases para el framework de seguridad.
java.sqlProvee interfaces y clases para procesar datos almacenados en fuentes de datos
como bases de datos.
java.textProvee interfaces y clases para manipular texto, fechas, números y mensajes.
java.utilContiene el framework de colecciones, modelo de eventos, servicios de fecha y
tiempo, internacionalización y clases misceláneas.
Clase

Una clase se define como un tipo abstracto de dato que contiene atributos y métodos. A través
de una clase se implementa un concepto abstraído de la realidad. En este caso, los atributos hacen referencia a las características del concepto abstraído y los métodos hacen referencia a los servicios del concepto abstraído. La sintaxis de la clase debe ser la siguiente.

public class MiClase{
 //Definición de atributos
 //Definición de métodos
}

En Java, se debe seguir una buena práctica que consiste en implementar cada clase en un archivo independiente con extensión .java. Para el ejemplo anterior, el archivo debe denominarse MiClase.java.

Atributos

Los atributos hacen referencia a las características que se le incluyen a la clase. Estos atributos pueden ser declaraciones de tipos primitivos de datos o declaraciones de clases.

Visibilidad

La visibilidad refiere al nivel de accesibilidad de los atributos y métodos. Los niveles de accesibilidad se dan por los siguientes términos:

  1. private. Se puede acceder desde un método implementado desde la misma clase.
  2. public. Se puede acceder desde un método implementado en cualquier clase.
  3. protected. Se puede acceder desde un método implementado en una clase que herede la clase que contiene esta visibilidad y desde clases implementadas en el mismo paquete.
Métodos

Los métodos hacen referencia a los servicios que se le incluyen en la clase. En estos métodos se implementa el código necesario del servicio. Un método contiene los siguientes elementos:

  1. Visibilidad. Se debe establecer si el método es private, public o protected.
  2. Retorno. Un método puede retornar información. Si el método no retorna información se debe colocar la palabra reservada “void”. El retorno puede ser un tipo primitivo de dato o una clase. Si un método tiene retorno, en la implementación del método debe estar presente la palabra reservada “return”.
  3. Nombre. Identificador del método en la clase.
  4. Parámetros. Un método puede recibir de 0 a n parámetros. Un parámetro puede ser un tipo primitivo de dato o una declaración de una clase. Los parámetros deben estar separados por comas.

Cada método implementa un código que debe estar contenido entre “{” y “}”. La sintaxis de los métodos es la siguiente.

//método publico sin retorno y sin parámetros 
public void miMetodo(){
 instrucción 1;
 instrucción 2;
 ..
 instrucción n;
}
//método privado con retorno int y sin parámetros
private int miMetodo(){
 instrucción 1;
 instrucción 2;
 ..
 instrucción n;
 return valorInt;
}
//método privado con retorno int y con parámetros
private int miMetodo(int parametro1, boolean parametro2, MiClase parametro3){
 instrucción 1;
 instrucción 2;
 ..
 instrucción n;
 return valorInt;
}
 
Encapsulamiento

Es una característica que indica que los atributos que definen propiedades propias de la clase deben tener visibilidad private. De esta forma se ofrece seguridad a la información depositada en dichos atributos.

Apuntador this

El apuntador this, permite acceder a los atributos y métodos de la clase. El uso del apuntador no es obligatorio, pero se recomienda usarlo como buena práctica. Es posible que el parámetro de un método tenga el mismo nombre que un atributo, en este caso el uso del apuntador this es obligatorio para que el compilador identifique si está haciendo referencia al atributo o al parámetro del método.

Objeto

Un objeto es la referencia e instancia de una clase. Al crear una referencia, se asigna un espacio de memoria dinámica al objeto, pero no es utilizable. Al crear la instancia, el objeto es utilizable. La sintaxis de la referencia es la siguiente.

MiClase m;

Donde m es la referencia del objeto. La sintaxis de la instancia es la siguiente

m = new MiClase();

Al hacer la instancia, se puede acceder a los atributos y métodos públicos y protegidos si aplica, a través del objeto m. Otra sintaxis para realizar referencia e instancia en la misma línea de código es la siguiente.

MiClase m = new MiClase();
Sentencia "Static"

Una clase puede tener atributos y/o métodos propios y no del objeto. La sentencia “static” define estos atributos y métodos de tal forma que puedan ser accedidos sin requerir una instancia de la clase. Por otro lado, un atributo “static”, toma el mismo valor para todos los objetos que sean instancia de la clase que lo contiene. Por ejemplo la clase Math contiene el método “sin” el cual calcula el seno de un parámetro dado.

Ejemplo

public class MiClase{
 public static int miValor;

 public static long factorial(long n) {
  long fact=1;
  for(int i=1; i<n; i++){
   fact *= i;
  }
  return fact;
 }
}

En donde se puede hacer uso del método factorial de la siguiente forma.

long valor = MiClase.factorial(5);

También permite hacer uso del atributo miValor de la siguiente forma.

MiClase c1 = new MiClase();
C1.miValor = 10;
MiClase c2 = new MiClase();
MiClase c3 = new MiClase();

En el código anterior, el atributo miValor tendrá el valor 10 para los objetos c1, c2 y c3, solo con asignarlo en un objeto de ellos, que para el caso es en c1.

Sentencia "Final"

Una clase puede tener atributos finales que hacen referencia a constantes que no pueden cambiar su valor en tiempo de ejecución de la aplicación. La sintaxis es la siguiente.

Por ejemplo el atributo “PI” cuyo valor se encuentra implementado en la clase de API de Java Math puede ser accedido sin requerir instancia de la clase Math y su valor es constante.

public class MiClase{
 public final int UNO=1;
 public final int DOS=2;
}
Clasificacion de Metodos

Los métodos se pueden clasificar en cuatro tipos que son los siguientes:

  1. Constructores. Un constructor es el primer método que se ejecuta al realizar la instancia de un objeto. Uno de los usos principales de un constructor es la inicialización de los atributos de la clase. El método constructor debe tener visibilidad pública y no posee retorno. La sintaxis es la siguiente.
  2. public class MiClase{
    
     //Definición de atributos
     private int atributo1;
     private int atributo2;
    
     //Definición de método constructor
     public MiClase(){
      this.atributo1=0;
      this.atributo1=0;
     }
    }
    
  3. Consultores. Un consultor es el método que permite retornar el valor de un atributo con visibilidad private al aplicar el concepto de encapsulamiento. La sintaxis es la siguiente.
  4. public class MiClase{
    
     //Definición de atributos
     private int atributo1;
     private int atributo2;
    
     //Método constructor
     public MiClase(){
      this.atributo1=0;
      this.atributo1=0;
     }
    
     //Método consultor
     public int getAtributo1() {
      return this.atributo1;
     }
    
     //Método consultor
     public int getAtributo2() {
      return this.atributo2;
     }
    }
    
  5. Modificadores. Un modificador es el método que permite asignar valor a un atributo con visibilidad private al aplicar el concepto de encapsulamiento. La sintaxis es la siguiente.
  6. public class MiClase{
    
     //Definición de atributos
     private int atributo1;
     private int atributo2;
    
     //Método constructor
     public MiClase(){
      this.atributo1=0;
      this.atributo1=0;
     }
    
     //Método consultor
     public int getAtributo1() {
      return this.atributo1;
     }
    
     //Método consultor
     public int getAtributo2() {
      return this.atributo2;
     }
    
     //Método modificador
     public void setAtributro1(int atributo1) {
      this.atributo1 = atributo1;
     }
    
     //Método modificador
     public void setAtributro2(int atributo2) {
      this.atributo2 = atributo2;
     }
    }
    
  7. Analizadores. Un analizador es el método que permite implementar la lógica del servicio del método, es decir, allí se implementan los algoritmos requeridos. La sintaxis es la siguiente.
  8. public class MiClase{
    
     //Definición de atributos
     private int atributo1;
     private int atributo2;
    
     //Método constructor
     public MiClase(){
      this.atributo1=0;
      this.atributo1=0;
     }
    
     //Método consultor
     public int getAtributo1() {
      return this.atributo1;
     }
    
     //Método consultor
     public int getAtributo2() {
      return this.atributo2;
     }
    
     //Método modificador
     public void setAtributro1(int atributo1) {
      this.atributo1 = atributo1;
     }
       
     //Método modificador
     public void setAtributro2(int atributo2) {
      this.atributo2 = atributo2;
     }
    
     //Método analizador
     public int calcularMayor() {
      if(this.atributo1 > this.atributo2){
       return this.atributo1;
      }else{
       return this.atributo2;
      }
     }
    }
    
Sobrecarga de Metodos

La sobrecarga de métodos es una característica que permite que varios métodos en una misma clase tengan el mismo nombre. La forma en que el compilador identifica cual es el método a utilizar en tiempo de ejecución se debe a que los métodos deben poseer diferentes parámetros y/o retorno. La diferencia puede estar dada en el número de parámetros y/o en el tipo de los mismos. Por ejemplo se plantean los siguientes métodos sobrecargados.

//Método sobrecargado 1. Sin parámetro y sin retorno.
public void miMetodo(){

}

//Método sobrecargado 2. Con parámetro y con retorno int.
public int miMetodo(int parametro1){

}

//Método sobrecargado 3. Con parámetros y con retorno boolean.
public boolean miMetodo(int parametro1, int parametro2){

}

//Método sobrecargado 4. Con parámetros diferentes a la sobrecarga 3 y con retorno boolean.
public boolean miMetodo(int parametro1, long parametro2){

}
Recursividad

Recursividad es la característica en la programación que permite hacer un llamado a un método desde el mismo método. Esta característica simplifica el desarrollo. Cada llamado recursivo, equivale a una iteración en una estructura de repetición como el “while” o “for”. Tiene la ventaja de utilizar casi los mismos recursos que en un proceso iterativo regular. Por otro lado, existen algoritmos que necesariamente deben ser implementados de forma recursiva como algoritmos fractales y arboles.

Para aplicar el concepto de recursividad, el método debe necesariamente retornar un valor, recibir por parámetro al menos un valor, implementar una condición de ruptura del proceso recursivo  e implementar una función recursiva.

Por ejemplo si se desea implementar el algoritmo del factorial, se podría implementar el siguiente método para resolver el algoritmo

public long factorial(long n) {
 long fact=1;
 for(int i=1; i<n; i++){
  fact *= i;
 }
 return fact;
}

Entonces, suponiendo que n=5, el algoritmo realiza 5 iteraciones, en donde en cada iteración se presentan los siguientes resultados en las variables:

  1. Primera iteración: fact=1*1=1
  2. Segunda iteración: fact=1*2=2
  3. Tercera iteración: fact=2*3=6
  4. Cuarta iteración: fact=6*4=24
  5. Quinta iteración: fact=24*5=120

También se puede hacer la implementación del algoritmo del factorial de forma recursiva.

public long factorial(long n) {
 if(n==1 || n==0){
  return 1;
 }else{
  return n*factorial(n-1);
 }
}

Otra forma más avanzada de codificar el mismo algoritmo recursivo es la siguiente.

public long factorial(long n) {
 return (n==1 || n==0)?1:n*factorial(n-1);
}

Entonces, suponiendo que n=5, el algoritmo realiza 5 llamadas recursivas, en donde en cada llamada se presentan los siguientes resultados.

  1. Primer llamada: retorna 5*factorial(4)
  2. Segunda llamada: retorna 4*factorial(3)
  3. Tercer llamada: retorna 3*factorial(2)
  4. Cuarta llamada: retorna 2*factorial(1)
  5. Quinta llamada: retorna 1

Para hacer el primer llamado al método se puede considerar la siguiente sentencia

long f = factorial(5);

En la siguiente figura se observa cómo cada llamada aporta a la consecución del resultado del algoritmo.

Bajo Acoplamiento

Es la característica en el paradigma de orientación a objetos que indica que los diferentes subsistemas deben estar unidos de forma mínima. Esto indica, que las clases que se construyen deben ser lo más reducidas sin involucrar elementos que impliquen conceptos diferentes a los tratados en la clase.

Un ejemplo de bajo acoplamiento podría ser una memoria USB. Esta memoria es un sistema totalmente independiente al sistema computador. Se conectan los dos sistemas a través del puerto USB y de forma automática, ambos sistemas quedan integrados. Además, esta operación se puede realizar mientras el computador se encuentre en funcionamiento. Así mismo es posible desconectar la memoria sin problemas.

Un ejemplo de alto acoplamiento con base en el anterior, es el disco duro. Este se encuentra altamente acoplado, debido a que no se puede desconectar mientras el computador se encuentra en funcionamiento. Además sin este sistema, el computador no puede funcionar. Por otro lado, un ejemplo de bajo acoplamiento es la memoria USB, la cual se puede conectar y desconectar de forma simple y no afecta ni al computador ni a la memoria misma.

Alta Cohesion

Es la característica en el paradigma de orientación a objetos que indica que las propiedades y servicios de una clase deben ser consistentes con el concepto que abstrae dicha clase.

Por ejemplo, si se tiene una clase Triangulo, esta clase podría contener los siguientes atributos:

  • Identificación
  • Base
  • Altura

Además podría tener servicios como:

  • Calcular Área
  • Calcular Perímetro

En este ejemplo la clase triangulo se encuentra altamente cohesionada ya que los atributos y métodos hacen referencia directa a características y comportamientos de concepto abstraído que es el triangulo.

Si se incluye por ejemplo el método calcular volumen, esta clase estaría bajamente cohesionada, ya que un triangulo no posee volumen. Este método tendría que ser trasladado a la clase pirámide.

Manejo de Excepciones

En el lenguaje Java, una “Exception” hace referencia a una condición anormal que se produce en tiempo de ejecución de la aplicación. Algunas excepciones son denominadas fatales, las cuales provocan la finalización de la ejecución de la aplicación. Generalmente las excepciones se generan por que falla la operación como consecuencia de un error de uso de la aplicación por parte del usuario. Para ilustrar el concepto, se presentan los siguientes ejemplos:

  • Si el usuario intenta abrir un archivo e ingresa de forma incorrecta la ruta del mismo, la aplicación presenta una excepción que debe controlarse para presentarle información de error de ruta del archivo al usuario.
  • Si el usuario desea ingresar un numero para realizar una operación aritmética, pero erróneamente ingresa un carácter, la aplicación presenta una excepción de formato de numero que debe controlarse para indicarle al usuario que no se puede realizar la operación aritmética.

Las excepciones se representan mediante clases derivadas de la clase Throwable, sin embargo, las clases con las que se desarrolla, se derivan de la clase Exception que pertenece al paquete java.lang.

Estructura try catch finally

Las excepciones en Java deben ser capturadas mediante el uso de las estructuras try, catch y finally. En el bloque try, se debe implementar el código del proceso que se desea ejecutar. En el bloque catch, se implementa el código alterno que se ejecutara en caso de que se presente una situación anormal o excepción en la ejecución del código implementado en el bloque try. Es posible tener varios bloques catch que resuelvan diferentes tipos de excepción. El bloque finally es opcional, pero en caso de implementarse, este se ejecutara independientemente si se presenta o no excepción. Este se implementa posterior a la implementación del bloque try y del bloque catch. La sintaxis es la siguiente:

public void miMetodo(){
 ...
 try{
  instrucción 1;
  instrucción 2;
  ...
  instrucción n;
 }catch (Exception e){
  //Instrucciones del manejo de la excepcion
 }finally{
  //Instrucciones que se ejecutan en cualquiera de los dos casos
 }
 ...
}
Sentencia throws y throw

En caso que el código de un método genere una “Exception” pero no se desee manejar dicha excepción, es posible enviar el manejo de la misma al método que hace el llamado. Este envío del manejo de la excepción se realiza mediante la inclusión de la sentencia “throws” seguida del nombre de la excepción posterior a los parámetros del método. Esta sentencia obliga a que el método que hace el llamado, implemente el manejo de la excepción a través del bloque try catch o envíe a su vez la excepción al método que hace el llamado a través de la sentencia throws. La sintaxis es la siguiente.

public void miMetodo() throws Exception{
 ...
 throw new Exception("Mi excepcion");
}
Excepciones estándar del API de Java

Las excepciones en Java se representan mediante dos tipos de clases derivadas de la clase Throwable que son Error y Exception.

La clase Error está relacionada con errores de compilación, errores del sistema o errores de la JVM. Estos errores son irrecuperables y no dependen del desarrollador.

La clase Exception es la que debe tener en cuenta el desarrollador, debido a que de esta se derivan clases que manejan las excepciones que pueden ser controladas en tiempo de ejecución. Las clases derivadas de Exception más usuales son:

  1. RuntimeException: Contiene excepciones frecuentes en tiempo de ejecución de la aplicación
  2. IOException: Contiene excepciones relacionadas con entrada y salida de datos

Las clases derivadas de Exception pueden pertenecer a distintos paquetes de Java. Algunas de ellas pertenecen a java.lang, otras a java.io y a otros paquetes. Por derivarse de la clase Throwable todos los tipos de excepciones pueden usar los métodos siguientes:

  1. String getMessage() Extrae el mensaje asociado con la excepción.
  2. String toString() Devuelve un String que describe la excepción.
  3. void printStackTrace() Indica el método donde se lanzó la excepción.
Creación de Excepciones en Java

En un proyecto es posible crear excepciones propias sólo con heredar de la clase Exception o de una de sus clases derivadas. Las clases derivadas de Exception suelen tener dos constructores:

  1. Un constructor sin argumentos.
  2. Un constructor que recibe un String como argumento. En este String se suele definir un mensaje que explica el tipo de excepción generada. Este mensaje debe enviarse a la clase Exception mediante la sentencia super(String).

La sintaxis es la siguiente

class MiExcepcion extends Exception {
 public MiExcepcion() { // Constructor por defecto
  super();
 }
 public MiExcepción(String s) { // Constructor con mensaje
  super(s);
 }
}

No hay comentarios:

Publicar un comentario