Programación Orientada a Objetos


Pilares



La POO tiene varios pilares para asegurar la simplicidad de código y su reutilización, y aunque diversos autores señalan diversos pilares, en este documento se considerarán los cuatro que son comunes en la mayoría de textos, estos son: Abstracción, Encapsulamiento, Herencia y Polimorfismo, las dos primeras están más relacionadas con la búsqueda de códigos simples y las dos siguientes con la reutilización.

Abstracción
Es el pilar de la POO, que permite identificar las características y comportamientos de un objeto y con los cuales se construirá la clase (plantilla). Esto quiere decir que a través de este pilar o fundamento es posible reconocer los atributos y métodos de un objeto.

La imagen muestra en texto de color negro algunas de las características del objeto: color, tamaño, marca, son características porque todos los controles pueden tenerlas y cada objeto de este tipo tomará valores que le identifiquen; el objeto de la imagen tiene los siguientes valores:




color: negro

tamaño: 15

marca: samsung

De igual forma, se identifican los comportamientos que en la imagen aparecen como textos de color blanco


Encapsulamiento

Es la característica de la POO que permite el ocultamiento de la complejidad del código, pertenece a la parte privada de la clase y que no puede ser vista desde ningún otro programa.


En el gráfico se representa como la complejidad del código queda oculta dentro de una caja fuerte impidiendo que quien lo utilice sin observar los detalles de cada una de las líneas que permiten el cumplimiento de una acción específica.



En realidad, el encapsulamiento está relacionado con el acceso a un código desde el código de otra clase; sin embargo en términos generales, esta representación gráfica es conveniente para comprender el concepto de encapsulamiento.

Herencia
Es el pilar más fuerte que asegura la reutilización de código, ya que a partir de esta característica es posible reutilizar (heredar) las características y comportamientos de una clase superior llamada clase padre, a sus clases hijas, denominadas clases derivadas. Esto implica que una vez desarrollado el código de una clase base, su código puede ser reutilizado por las clases derivadas.

En el gráfico, Persona es la clase Padre, que tiene como características: CI, nombre, dirección, fechaNac, genero, entre otros; y Estudiante y Profesor son las clases "Hijas", que heredan las características de la clase padre y a su vez establecen las propias de su clase. Esto implica que no se deberán volver a definir, sino que por el simple hecho de heredarlas ya es posible utilizarlas y en el caso de los comportamientos ejecutarlos o modificarlos si es necesario.


Polimorfismo

A través de esta característica es posible definir varios métodos o comportamientos de un objeto bajo un mismo nombre, de forma tal que es posible modificar los parámetros del método, o reescribir su funcionamiento, o incrementar más funcionalidades a un método.

En el gráfico se observa que todas son figuras geométricas por lo que pueden incluirse en una clase Padre, por lo que la clase deberá tener el método Área(), este método podrá ser reescrito tantas veces como figuras existan, con los parámetros correspondientes en cada clase derivada: Circulo, Triangulo y Rectángulo, o reescrita en la clase base.




Clase

Las clases son plantillas que agrupan comportamiento (métodos) y estados (atributos) de los futuros objetos.

Los objetos son instancias de una clase. Usando el símil “variable – tipo” de la programación estructurada, se entiendo que un objeto es una variable que tiene el comportamiento y estados del tipo (objeto)

Objetos

Se puede decir que un objeto es todo aquello que pueda ser identificable dentro de una especificación de requerimientos o problema y tenga las siguiente características:
Tenga estados definibles (abierto, cerrado).

  • Posea comportamientos asociados (puede correr, saltar, volar, etc). Éstos son denominados métodos.
  • Son capaces de interactuar/comunicarse con otros objetos por medio de sus métodos

Una característica propia de este paradigma, es la transparencia entre la implementación a nivel de código y la funcionalidad que provee un método (no me interesa cómo lo haga, sólo que lo haga).


Componentes de clase

  • Los atributos son las propiedades o características significativas de los objetos de esa clase. Por ejemplo, una clase ‘Alumno’ podría tener los atributos nombre, DNI, edad, sexo, calificación, … y cada objeto alumno tomaría unos valores determinados de ese conjunto de atributos compartidos. Serían los datos, el estado del objeto.
  • Los métodos son las operaciones o procedimientos que pueden realizar los objetos de esa clase. Sería su comportamiento.

Parámetros y argumentos

Parámetros y argumentos (programación): Un argumento o parámetro es el medio a partir del cual podemos expandir el ámbito de variables locales de funciones, hacia otras funciones y además quienes nos permiten establecer comunicaciones entre funciones. Si nos vemos ante la necesidad de visualizar o modificar el valor de una variable local en otra función que llamaremos, debemos invocar a dicha función haciendo referencia de su nombre, seguido de los parámetros o nombres de variables para las cuales, en teoría ampliaríamos su ámbito.

Las palabras parámetro y argumento, aunque de significado similar, tiene distintas connotaciones semánticas: Se denominan parámetros los tipos declarados en el prototipo (que deben corresponder con los declarados en la definición). Cuando se realiza una llamada a la función, los "valores" pasados se denominan argumentos. A veces se utilizan también las expresiones argumentos formales, para los parámetros y argumentos actuales para los valores pasados.



Métodos con retorno


Métodos tipo función: son métodos que nos devuelven algo. Un método es tipo función si comienza con un tipo (no consideramos ahora la palabra clave public). Por ejemplo String getDistrito() comienza con el tipo String lo que significa que nos devuelve una cadena de caracteres, mientras que int getTipoMotor() comienza con el tipo int lo que significa que nos devuelve un entero. Tener en cuenta que un método tipo función devuelve solo un dato u objeto como resultado, no varios. La devolución del resultado se expresa con la palabra clave return seguida del dato u objeto a devolver, por ejemplo return tipoMotor;. La sentencia return implica que termina la ejecución del código en el método y estará típicamente en la línea final. De existir una línea por detrás de una sentencia return, nunca llegaría a ejecutarse (tendremos que matizar esto porque el uso de condicionales nos permitirá tener más de un return en un método). 

El retorno de un método puede hacerse de tres maneras:

1.- Cuando el método finaliza.

2.- Cuando se encuentra con la sentencia “return”.

3.- Cuando se lanza una excepción.

Es muy común que en el retorno del método se encuentre el resultado de una operación, aunque puede ser utilizado para otros fines, como el detener la ejecución del mismo método, esto se hace mediante la sentencia “return”.

La sentencia return puede ser o no la última instrucción del cuerpo del método, además puede aparecer una o más veces. 
 Se puede omitir la sentencia return en caso de que el método no retorne un valor (void).

Funciones sin retorno

El tipo de dato que debe indicar en la cabecera de declaración del método es el tipo void y la sentencia return no viene seguida de ninguna expresión.

Métodos tipo procedimiento: son métodos que realizan ciertas operaciones sin devolver un valor u objeto concreto. Un método es tipo procedimiento si comienza con la palabra clave void (que traducido del inglés viene siendo “vacío” o “nulo”). En estos casos podemos decir que el tipo de retorno es void.

Setters & Getters
Los Setters & Getters son métodos de acceso lo que indica que son siempre declarados públicos, y nos sirven para dos cosas:

Setters: Del Inglés Set, que significa establecer, pues nos sirve para asignar un valor inicial a un atributo, pero de forma explícita, además el Setter nunca retorna nada (Siempre es void), y solo nos permite dar acceso público a ciertos atributos que deseemos el usuario pueda modificar.

Getters: Del Inglés Get, que significa obtener, pues nos sirve para obtener (recuperar o acceder) el valor ya asignado a un atributo y utilizarlo para cierto método.


Tipos de métodos

Un método es una abstracción de una operación que puede hacer o realizarse con un objeto. Una clase puede declarar cualquier número de métodos que lleven a cabo operaciones de lo más variado con los objetos. En esta sección los métodos se clasifican en dos grupos: los métodos de instancia y los métodos de clase.



MÉTODOS DE INSTANCIA

Las clases pueden incluir en su declaración muchos métodos o no declarar ninguno. Los métodos pueden clasificarse en métodos de instancia y métodos de clase.

Los métodos de instancia operan sobre las variables de instancia de los objetos pero también tienen acceso a las variables de clase. La sintaxis de llamada a un método de instancia es:

// Llamada tipica a un metodo de instancia
idReferencia.idMetodo(parametros);

Todas las instancias de una clase comparten la misma implementación para un método de instancia. La instancia que hace la llamada al método es siempre un parámetro o argumento implícito. Dentro de un método de instancia, el identificador de una variable de instancia hace referencia al atributo de la instancia concreta que hace la llamada al método (suponiendo que el identificador del atributo no ha sido ocultado por el de un parámetro).

public double saldo() {
    return this.saldo;
}

 
public void transferencia( CuentaBancaria origen ) {
   this.saldo += origen.saldo;
   origen.saldo = 0;
}

Ejemplos de llamada a estos métodos dentro de PruebaCuentaBancaria:
CuentaBancaria c1 = new CuentaBancaria();
CuentaBancaria c2 = new CuentaBancaria(20.0);
 
c1.transferencia(c2);
System.out.println("Cuenta con: " + c1.saldo() + " euros");

MÉTODOS DE CLASE
En principio, los métodos de clase no operan sobre las variables de instancia de los objetos. Los métodos de clase pueden trabajar con las variables de clase pero no pueden acceder a las variables de instancia declaradas dentro de la clase, a no ser que se crea una nueva instancia y se acceda a las variables de instancia a través del nuevo objeto. Los métodos de clase también pueden ser llamados precediendolos con el identificador de la clase, sin necesidad de utilizar el de una instancia.
IdClase.idMetodo(parametros); // Llamada tipica a un metodo de clase
La palabra static determina la declaración de un método de clase. Por defecto, si no se indica la palabra static, el método declarado se considera un método de instancia.
En el ejemplo anterior en la declaración de la clase CuentaBancaria, el método incCuentas es un método de clase.
public static void incCuentas () {
    totalCuentas++;
}
Un ejemplo de llamada a este método dentro de PruebaCuentaBancaria sería:
CuentaBancaria.incCuentas();

Las diferencias entre los métodos de instancia y los de clase se resumen aquí:
Constructor
Un "constructor" es un método especial que se ejecuta en el momento que se crea un objeto de la clase (new).  Su misión es reservar memoria e inicializar las variables miembro de la clase.

Debemos tener en cuenta ciertas cosas a la hora de crear un constructor:

  • Los constructores no tienen valor de retorno, ni siquiera "void".
  • El nombre tiene que ser el mismo que el de la clase.
  • Una clase puede tener varios constructores, se diferencian así mismo por la cantidad de argumentos y su tipo(sobrecargados), mas adelante explicaremos lo que son métodos sobrecargados y sobrescritos.
  • En caso de no poner ningún constructor, Java nos pone un por defecto (invisible), con el mismo nombre y modificador de acceso que la clase y con una sola linea de código (super()). TODAS las clases llevan constructor, ya sea explicito o implícito.
Sobrecarga de métodos

En Java, dos o más métodos dentro de la misma clase pueden compartir el mismo nombre, siempre que sus declaraciones de parámetros sean diferentes.

Cuando este es el caso, se dice que los métodos están sobrecargados, y el proceso se denomina sobrecarga de métodos (method overloading). La sobrecarga de métodos es una de las formas en que Java implementa polimorfismo.

En general, para sobrecargar un método, simplemente declare versiones diferentes de él. El compilador se ocupa del resto. Debe observar una restricción importante: el tipo y/o el número de parámetros de cada método sobrecargado debe diferir. No es suficiente que dos métodos difieran solo en sus tipos de devolución.


Los tipos de devolución no proporcionan información suficiente en todos los casos para que Java decida qué método utilizar.


Por supuesto, los métodos sobrecargados también pueden diferir en sus tipos de devolución. Cuando se llama a un método sobrecargado, se ejecuta la versión del método cuyos parámetros coinciden con los argumentos.

Modificadores en Java

DEFAULT
Si no elegimos ningún modificador, se usa el de por defecto, que sólo puede ser accedido por clases que están en el mismo paquete.

PUBLIC
Este nivel de acceso permite a acceder al elemento desde cualquier clase, independientemente de que esta pertenezca o no al paquete en que se encuentra el elemento.

PRIVATE
Es el modificador más restrictivo y especifica que los elementos que lo utilizan sólo pueden ser accedidos desde la misma clase en la que se encuentran. Este modificador sólo puede utilizarse sobre los miembros de una clase y sobre interfaces y clases internas, no sobre clases o interfaces de primer nivel, dado que esto no tendría sentido.

PROTECTED
Indica que los elementos sólo pueden ser accedidos desde su mismo paquete y desde cualquier clase que extienda la clase en que se encuentra, independientemente de si esta se encuentra en el mismo paquete o no. Este modificador, como private, no tiene sentido a nivel de clases o interfaces no internas.

En otras palabras, si determinada clase Hijo hereda el comportamiento de una clase Padre, la clase Hijo tendrá acceso a todos aquellos campos/métodos definidos como protected en Padre, pero no aquellos declarados como private en Padre.



Modificadores de clases y métodos: STATIC, FINAL, ABSTRACT.

STATIC
Sirve para crear miembros que pertenecen a la clase, y no a una instancia de la clase. Esto implica, entre otras cosas, que no es necesario crear un objeto de la clase para poder acceder a estos atributos y métodos.

En ocasiones es necesario o conveniente generar elementos que tomen un mismo valor para cualquier número de instancias generadas o bien invocar/llamar métodos sin la necesidad de generar instancias, y es bajo estas dos circunstancias que es empleado el calificador static.

Dos aspectos característicos de utilizar el calificador static en un elemento Java son los siguientes:

– No puede ser generada ninguna instancia (uso de new) de un elemento static puesto que solo existe una instancia.

– Todos los elementos definidos dentro de una estructura static deben ser static ellos mismos, o bien, poseer una instancia ya definida para poder ser invocados.

NOTA: Lo anterior no implica que no puedan ser generadas instancias dentro de un elemento static; no es lo mismo llamar/invocar que crear/generar.

FINAL
Indica que una variable, método o clase no se va a modificar, lo cuál puede ser útil para añadir más semántica, por cuestiones de rendimiento, y para detectar errores.

– Si una variable se marca como final, no se podrá asignar un nuevo valor a la variable.
– Si una clase se marca como final, no se podrá extender la clase.
– Si es un método el que se declara como final, no se podrá sobreescribir.

Algo muy a tener en cuenta a la hora de utilizar este modificador es que si es un objeto lo que hemos marcado como final, esto no nos impedirá modificar el objeto en sí, sino tan sólo usar el operador de asignación para cambiar la referencia


ABSTRACT
La palabra clave abstract indica que no se provee una implementación para un cierto método, sino que la implementación vendrá dada por las clases que extiendan la clase actual. Una clase que tenga uno o más métodos abstract debe declararse como abstract a su vez.

Método abstracto

En una clase abstracta es posible definir métodos abstractos, los cuales se caracterizan por el hecho de que no pueden ser implementados en la clase base. De ellos, solo se escribe su signatura en la superclase, y su funcionalidad –polimórfica– tiene que indicarse en las clases derivadas (subclases).

Además un método abstracto tiene estas peculiaridades:

a) No tiene cuerpo (llaves): sólo consta de signatura con paréntesis.

b) Su signatura termina con un punto y coma.

c) Sólo puede existir dentro de una clase abstracta. De esta forma se evita que haya métodos que no se puedan ejecutar dentro de clases concretas. Visto de otra manera, si una clase incluye un método abstracto, forzosamente la clase será una clase abstracta.

d) Los métodos abstractos forzosamente habrán de estar sobreescritos en las subclases. Si una subclase no implementa un método abstracto de la superclase tiene un método no ejecutable, lo que la fuerza a ser una subclase abstracta. Para que la subclase sea concreta habrá de implementar métodos sobreescritos para todos los métodos abstractos de sus superclases.


Clases abstractas

En Java se dice que son clases abstractas aquellas clases base (superclases) de las que no se permite la creación de objetos. Para ello, se utiliza la palabra clave abstract

clase Abstracta es similar a una clase normal, la estructura es prácticamente igual, ya que poseen nombre, atributos y métodos pero para que una clase sea abstracta la condición es que al menos uno de sus métodos sea abstracto (se le agrega la palabra reservada abstract y no se especifica el cuerpo del método).................su uso depende de la aplicación del concepto de Herencia y adicionaremos a la estructura básica de clase la palabra reservada abstract.


INTERFACES

Una interfaz es una especie de plantilla para la construcción de clases. Normalmente una interfaz se compone de un conjunto de declaraciones de cabeceras de métodos (sin implementar, de forma similar a un método abstracto) que especifican un protocolo de comportamiento para una o varias clases. Además, una clase puede implementar una o varias interfaces: en ese caso, la clase debe proporcionar la declaración y definición de todos los métodos de cada una de las interfaces o bien declararse como clase abstract. Por otro lado, una interfaz puede emplearse también para declarar constantes que luego puedan ser utilizadas por otras clases.

  • Una interfaz puede parecer similar a una clase abstracta, pero existen una serie de diferencias entre una interfaz y una clase abstracta:
  • Todos los métodos de una interfaz se declaran implícitamente como abstractos y públicos.
  • Una clase abstracta no puede implementar los métodos declarados como abstractos, una interfaz no puede implementar ningún método (ya que todos son abstractos).
  • Una interfaz no declara variables de instancia.
  • Una clase puede implementar varias interfaces, pero sólo puede tener una clase ascendiente directa.
  • Una clase abstracta pertenece a una jerarquía de clases mientras que una interfaz no pertenece a una jerarquía de clases. En consecuencia, clases sin relación de herencia pueden implementar la misma interfaz.

Arrays

En Java, un Array o (en español arreglo) es un grupo de variables llamadas elementos o componentes que contienen variables las cuales son de un mismo tipo. En java, a diferencia del lenguaje C, existe un tipo de variable “especial”, el Array o matriz. Este tipo de variables no es más que un conjunto secuencial de memoria a las que se accede a través de un índice de posición.

Las matrices en Java son objetos, por lo que cuentan con propiedades y métodos para manipularlos. Se pueden declarar matrices de tipos de datos primitivos y de objetos.

Para hacer referencia a un elemento en especial en un arreglo, se debe especificar el nombre que llevará la referencia al arreglo y el número de la posición del elemento en el arreglo. El número de la posición del elemen- to se conoce como el índice o subíndice del elemento.

Existen varias maneras de declarar un array, por ejemplo:
Sintaxis:

  • tipodedato nombre [] = new tipodedato[tamaño]
  • int c[] = new int[ 12 ];
    

  • tipodedato[] nombre = new tipodedato[tamaño]
  • int[] c = new int[ 12 ];
    

  • tipodedato nombre [] nombre = new tipodedato[tamaño]
  • int c[ ];
    c = new int[ 12 ];
    

    Colecciones
    Una colección representa un grupo de objetos. Esto objetos son conocidos como elementos. Cuando queremos trabajar con un conjunto de elementos, necesitamos un almacén donde poder guardarlos. En Java, se emplea la interfaz genérica Collection para este propósito. Gracias a esta interfaz, podemos almacenar cualquier tipo de objeto y podemos usar una serie de métodos comunes, como pueden ser: añadir, eliminar, obtener el tamaño de la colección… Partiendo de la interfaz genérica Collection extienden otra serie de interfaces genéricas. Estas subinterfaces aportan distintas funcionalidades sobre la interfaz anterior.

    List

    La interfaz List define una sucesión de elementos. A diferencia de la interfaz Set, la interfaz List sí admite elementos duplicados. A parte de los métodos heredados de Collection, añade métodos que permiten mejorar los siguientes puntos:
    • Acceso posicional a elementos: manipula elementos en función de su posición en la lista.
    • Búsqueda de elementos: busca un elemento concreto de la lista y devuelve su posición.
    • Iteración sobre elementos: mejora el Iterator por defecto.
    • Rango de operación: permite realizar ciertas operaciones sobre ragos de elementos dentro de la propia lista.

    Dentro de la interfaz List existen varios tipos de implementaciones realizadas dentro de la plataforma Java.

    Map

    La interfaz Map asocia claves a valores. Esta interfaz no puede contener claves duplicadas y; cada una de dichas claves, sólo puede tener asociado un valor como máximo.

    Dentro de la interfaz Map existen varios tipos de implementaciones realizadas dentro de la plataforma Java.

    Collection

    La interfaz más importante es Collection. Una Collection es todo aquello que se puede recorrer (o “iterar”) y de lo que se puede saber el tamaño. Muchas otras clases extenderán Collection imponiendo más restricciones y dando más funcionalidades. Es de notar que el requisito de “que se sepa el tamaño” hace inconveniente utilizar estas clases con colecciones de objetos de las que no se sepa “a priori” la cantidad.

    Por las dudas vuelvo a aclarar: No puedo construir una Collection. No se puede hacer “new” de una Collection, sino que todas las clases que realmente manejan colecciones “son” Collection, y admiten sus operaciones.

    Las operaciones básicas de una collection entonces son:
    add(T)
    Añade un elemento.
    iterator()
    Obtiene un “iterador” que permite recorrer la colección visitando cada elemento una vez.
    size()
    Obtiene la cantidad de elementos que esta colección almacena.
    contains(t)
    Pregunta si el elemento t ya está dentro de la colección.




    No hay comentarios.:

    Publicar un comentario

    JavaScript

    JavaScript