Tema 15: Programacion Orientada a Objetos (POO).
1.- Conceptos generales.
La POO es un paradigma surgido en los años 1970, que utiliza objetos como elementos fundamentales en la construcción de la solución. Un objeto es una abstracción de algún hecho o ente del mundo real, con atributos que representan sus características o propiedades, y métodos que emulan su comportamiento o actividad.
2.- Clases y objetos.
Un ejemplo para clases y objetos en Java
Vamos a imaginar que somos los dueños o administradores de una fábrica de galletas, vendemos diferentes tipos de galletas con diferentes formas, sabores y colores, evidentemente al tener diferentes formas para nuestras galletas necesitaremos varios moldes para las galletas que fabricamos (un molde para cada forma), necesitaremos diferentes recetas para el sabor de cada una y por último diferentes maneras de darle color a las galletas.
¿Qué son las clases en Java?
Una clase en Java se puede entender como un prototipo que define las variables y los métodos comunes a un cierto tipo de instancias, una clase define todo lo que caracteriza y pueden hacer una o varias instancias.
En nuestro ejemplo de la fábrica de galletas, la clase sería uno de los moldes para galletas, junto con los métodos para colorearlas y la receta (método para prepararlas). Quiere decir que en nuestro programa de Java tendremos una manera de especificar las características de la galleta dado que hay diferentes moldes de galletas.
En java las clases son las matrices de las que luego se pueden crear múltiples instancias del mismo tipo. La clase define las variables y los métodos comunes a las instancias de ese tipo (el tipo de la clase creada), pero luego, cada instancia de esta clase tendrá sus propios valores (su propio molde, color y receta) y compartirán las mismas funciones.
En java, primero deberemos crear una clase antes de poder crear instancias o ejemplares de esa clase. Evidentemente primero necesitamos los moldes y demás para poder hacer las galletas.
¿Qué son los objetos en Java?
En Java, un objeto es básicamente una instancia de una clase (las instancias de las que hablábamos hace un momento). Para el ejemplo de la fábrica de galletas, los objetos vendrían siendo cada una de las diferentes galletas obtenidas de los moldes definidos (clases), creados por medio de un proceso o "contructor" de galletas.
Muy bien, ya hemos hecho un repaso sobre el concepto de clase y objeto en Java, sin embargo aún no sabemos cómo crearlos ni usarlos, así que vamos a ello.
¿Cómo crear una clase en Java?
Como dije anteriormente la clase es la que nos dice los componentes del ejemplar que vamos a crear, es decir, una clase contiene los atributos y los métodos que conformarán al ejemplar o instancias, de este modo al momento de crear una clase en Java, debemos especificar el tipo y el nombre (como mínimo) de los atributos y adicionalmente debemos especificar (si existen) los métodos o funciones, el tipo de dato que retornan, el nombre y los parámetros que reciben dichos métodos.
Veamos la estructura básica de una clase en Java y luego veamos unos ejemplos de clases en java un poco más complejos e ilustrativos.
Estructura básica de una clase en Java
En el ejemplo anterior hemos creado una clase en Java llamada "MiClase" la cual posee un total de tres atributos (todos ellos privados) y son de tipo String, int y float respectivamente. Adicionalmente esta clase tiene un constructor (que siempre por norma, debe tener el mismo nombre de la clase) el cual no recibe ningún parámetro, aunque pueden recibir todos los parámetros que nosotros deseemos, también tiene un método llamado "metodo1" que no retorna valor alguno (es de tipo void) y otro método llamado "metodo2" que retorna una cadena de caracteres (es de tipo String) con el valor "metodo2". Cabe resaltar que una clase en Java puede tener o no métodos y atributos, sin embargo lo más normal en la mayoría de los casos es que tenga tanto métodos como atributos que la caractericen.
Veamos ahora un ejemplo un poco más completo e ilustrativo.
Ejemplo de clases en Java
La clase Java que hemos creado para este ejemplo tiene como nombre "Animal", pertenece al paquete "misClases" y posee los atributos raza, nombre y edad, adicionalmente tenemos un constructor que recibe un nombre y se lo asigna al animal y tres métodos encargados de obtener y establecer la edad del animal y el restante para obtener el nombre.
Objetos en Java
Muy bien, ya hemos aprendido a la perfección cómo crear clases en java, y cuáles son sus componentes esenciales, ahora vamos a aprender a crear objetos en Java, cómo se hace, veremos brevemente la utilidad y funcionamiento de los constructores y como usar los métodos
¿Cómo crear objetos en Java?
Al momento de crear objetos en Java, debemos tener claras dos cosas indispensables, la primera es el nombre de la clase para la cual vamos a crear el objeto y segundo el constructor que dicha clase posee, es decir, si el constructor recibe o no parámetros.
Para crear objetos en Java, el lenguaje nos proporciona el comando new, con este comando le decimos a Java que vamos a crear un nuevo objeto de una clase en especifico y le enviamos los parámetros (en caso de ser necesario) según el constructor, veamos un ejemplo.
Ejemplo de objetos en java
Vamos a crear un objeto o instancia en Java para la clase que hemos creado al comienzo llamada MiClase. Esta clase tiene un constructor que no recibe parámetros, por lo cual no es necesario enviar algún tipo de valor al momento de crear el objeto, veamos entonces la sintaxis para crear un objeto del tipo MiClase en java.
Otra forma de hacer y que también es válida es la siguiente:
Ejemplo 2 de objetos en Java
Vamos ahora a crear un objeto o instancia para la clase Animal (la del ejemplo dos), en esta ocasión tenemos un constructor que recibe un parámetro (el nombre del animal) y que posee tres métodos de los cuales haremos uso para este ejemplo.
4.- Métodos.




Esto solo es uno de los muchos que hay.
6.- Parametros y argumentos.
DECLARACIÓN DE PARÁMETROS
Los parámetros se declaran en la cabecera de la declaración de los métodos. Al declararse el parámetro, se indica el tipo de dato y el identificador correspondiente. Los parámetros o argumentos de un constructor o de un método pueden ser de cualquier tipo, ya sean tipos primitivos o referencias de objetos (en este caso debe indicarse el identificador de la clase correspondiente). Ejemplos de declaraciones de cabeceras de métodos:
// Sin parametros public double devuelve() { return ...; } // Un parametro, x de tipo double public void asigna(double x) { ... } // Dos parametros, a y b de tipo int public int elMayor(int a, int b) { ... } // Un parametro, v, array real public static double sumatorio (double [] v) { ... } // Un parámetro de la clase Fecha public boolean caducado (Fecha fechaLimite) { ... }
El identificador del parámetro se emplea sólo dentro del método para hacer referencia al argumento correspondiente y puede coincidir con el de un atributo de la misma clase. En tal caso, se dice que oculta a la variable miembro. Esta técnica suele emplearse en los constructores para inicializar una instancia. Por ejemplo en la clase
Circulo
:public class Circulo { int x, y, radio; public Circulo(int x, int y, int radio) { ... } }
La clase
Circulo
tiene tres atributos o variables miembro x
, y
y radio
y un constructor con tres argumentos con los mismos identificadores que facilitan los valores iniciales a los atributos respectivamente. Los identificadores de los parámetros ocultan a las variables miembro dentro del cuerpo del constructor, de forma que x
, y
y radio
dentro del constructor hacen referencia a los parámetros y no a las variables miembro. Para acceder a las variables miembro, es necesario emplear la palabra reservada this
que referencia a la instancia que está siendo inicializada por el constructor.public class Circulo { int x, y, radio; public Circulo(int x, int y, int radio) { this.x = x; // this.x hace referencia al atributo x // x hace referencia al parametro x this.y = y; // this.y hace referencia al atributo y // y hace referencia al parametro y this.radio = radio; } }
Normalmente dentro del cuerpo del método de una clase puede hacerse referencia directa a las variables miembro de las instancias. Salvo en el caso del ejemplo anterior en el que las variables miembro están ocultas. Por otro lado, los parámetros de un mismo método no puede compartir el mismo identificador (no pueden coincidir) con el de una variable local. El siguiente código genera un error de compilación:
public void asigna(double x) { // Un parametro, x de tipo double double x; // Error de compilacion ... }
7.- Retorno de valores.
Parámetros y argumentos
Estos dos términos; parámetros y argumentos, son a menudo intercambiados incorrectamente en su uso. El contexto ayuda a diferenciar su significado. El término parámetro, se usa a menudo para referirse a la variable en la declaración del método, mientras que argumento, se refiere al valor que se envia. Para evitar confusiones, es común ver a un parámetro como una variable y un argumento como un valor.
Los parámetros aparecen en la declaración de los métodos y los argumentos en las llamadas a los métodos. En la declaración del método, la variable es un parámetro y en la llamada del método, la variable es el argumento del método.
En el ejemplo del video tutorial (clase Tutorial11, que está al final de la página), vemos por ejemplo, que en el método insertarDatosArray(array, scanner), array y scanner son los argumentos y en la declaración del método,
array y scanner son los parámetros.
private static void insertarDatosArray(int[] array, Scanner scanner) { for (int i = 0; i < array.length; i++) { System.out.print("insertar array[" + i + "]:"); array[i] = scanner.nextInt(); } }
Métodos con retorno
Un método vuelve al código del que se llamó en el momento en el que alguna de estas circunstancias se de:
- se completan todas las sentencias del método,
- llega a una sentencia retorno o
- lanza una excepción,
El tipo de retorno de un método se especifica en la declaración del método. Dentro del cuerpo del método, se utiliza la sentencia return para devolver el valor.
Cualquier método que esté declarado como void, no devolverá ningún valor.
Si se intenta devolver un valor desde un método declarado void, aparecerá un error de compilación.
Cualquier método que no sea declarado void, deberá contener una sentencia return con su correspondiente valor de retorno;
return valorRetorno;
El tipo de dato del valor de retorno deberá coincidir con el tipo de retorno de la declaración del método. No se puede retornar un valor integer, a un método en el que en su declaración aparece como valor de retorno, un boolean.
package com.edu4java.Tutorial11; import java.util.Scanner; public class Tutorial11 { public static void main(String[] args) { int[] array = new int[5]; Scanner scanner = new Scanner(System.in); insertarDatosArray(array, scanner); sumarArray(array); int max = maxArray(array); System.out.println("Max= " + max); double promedio = promedioArray(array); System.out.println("Promedio= " + promedio); } private static void insertarDatosArray(int[] array, Scanner scanner) { for (int i = 0; i < array.length; i++) { System.out.print("insertar array[" + i + "]:"); array[i] = scanner.nextInt(); } } private static void sumarArray(int[] array) { System.out.print("Suma: "); int acumulador = 0; for (int i = 0; i < array.length; i++) { acumulador = acumulador + array[i]; System.out.print("+" + array[i]); } System.out.println("= " + acumulador); } private static int maxArray(int[] array) { int max = 0; for (int i = 0; i < array.length; i++) { if (array[i] > max) { max = array[i]; } } return max; } private static double promedioArray(int[] array) { double promedio = 0; for (int i = 0; i < array.length; i++) { promedio = promedio + array[i]; } promedio = promedio / array.length; return promedio; } }
8.- Método constructor.
CÓMO CREAR CONSTRUCTORES EN JAVA. EJERCICIOS EJEMPLOS RESUELTOS.
Los constructores de una clase son fragmentos de código que sirven para inicializar un objeto a un estado determinado. Una clase puede carecer de constructor, pero esto no es lo más habitual. Normalmente todas nuestras clases llevarán constructor. En un constructor es frecuente usar un esquema de este tipo:
public MismoNombreQueLaClase (tipo parámetro1, tipo parámetro2 …, tipo parámetro n ) {
campo1 = valor o parámetro;
campo2 = valor o parámetro;
.
.
.
campo n = valor o parámetro;
}
|
Los constructores tienen el mismo nombre que la clase en la que son definidos y nunca tienen tipo de retorno, ni especificado ni void. Tenemos aquí un aspecto que nos permite diferenciar constructores de métodos: un constructor nunca tiene tipo de retorno mientras que un método siempre lo tiene. Es recomendable que en un constructor se inicialicen todos los atributos de la clase aunque su valor vaya a ser nulo o vacío. Si un atributo se quiere inicializar a cero (valores numéricos) siempre lo declararemos específicamente: nombreAtributo = 0;. Si un atributo se quiere inicializar a contenido nulo (atributos que son objetos) siempre lo declararemos específicamente: nombreAtributo = null;. Si un atributo tipo texto se quiere inicializar vacío siempre lo declararemos específicamente: nombreAtributo = “”;. El motivo para actuar de esta manera es que declarando los atributos como nulos o vacíos, dejamos claro que esa es nuestra decisión como programadores. Si dejamos de incluir uno o varios campos en el constructor puede quedar la duda de si hemos olvidado inicializar ese campo o inducir a pensar que trabajamos con malas prácticas de programación.
La inicialización de campos y variables es un proceso muy importante. Su mala definición es fuente de problemas en el desarrollo de programas. Como regla de buena programación, cuando crees campos o variables, procede de forma inmediata a definir su inicialización.
Un constructor puede:
a) Carecer de parámetros: que no sea necesario pasarle un parámetro o varios al objeto para inicializarse. Un constructor sin parámetros se denomina “constructor general”.
b) Carecer de contenido. Por ejemplo, public Taxi () { } podría ser un constructor, vacío. En general un constructor no estará vacío, pero en algunos casos particulares puede estarlo. Si el constructor carece de contenido los campos se inicializan con valor nulo o, si son tipos definidos en otra clase, como se haya definido en el constructor de la otra clase. Excepto en casos controlados, evitaremos que existan constructores vacíos.
Si un constructor tiene parámetros, el funcionamiento es análogo al que ya hemos visto para métodos. Cuando vayamos a crear el objeto con BlueJ, se nos pedirá además del nombre que va a tener el objeto, el valor o contenido de los parámetros requeridos. Un parámetro con frecuencia sirve para inicializar el objeto como hemos visto, y en ese caso el objeto tendrá el valor pasado como parámetro como atributo “para siempre”, a no ser que lo cambiemos por otra vía como puede ser un método modificador del atributo. No obstante, en algunos casos los parámetros que recibe un constructor no se incorporarán directamente como atributos del objeto sino que servirán para realizar operaciones de diversa índole. Escribe y compila el siguiente código:
public class Taxi { //El nombre de la clase
private String ciudad; //Ciudad de cada objeto taxi
private String matricula; //Matrícula de cada objeto taxi
private String distrito; //Distrito asignado a cada objeto taxi
private int tipoMotor; //Tipo de motor asignado a cada objeto taxi. 0 = desconocido, 1 = gasolina, 2 = diesel
//Constructor: cuando se cree un objeto taxi se ejecutará el código que incluyamos en el constructor
public Taxi (String valorMatricula, String valorDistrito, int valorTipoMotor) {
ciudad = "México D.F.";
matricula = valorMatricula;
distrito = valorDistrito;
tipoMotor = valorTipoMotor;
} //Cierre del constructor
//Método para obtener la matrícula del objeto taxi
public String getMatricula () { return matricula; } //Cierre del método
//Método para obtener el distrito del objeto taxi
public String getDistrito () { return distrito; } //Cierre del método
//Método para obtener el tipo de motor del objeto taxi
public int getTipoMotor () { return tipoMotor; } //Cierre del método
} //Cierre de la clase
|
9.- Sobre carga de metodos.
Sobrecarga de métodos y de constructores
La firma de un método es la combinación del tipo de dato que regresa, su nombre y su lista de argumentos.
La sobrecarga de métodos es la creación de varios métodos con el mismo nombre pero con diferentes firmas y definiciones. Java utiliza el número y tipo de argumentos para seleccionar cuál definición de método ejecutar.
Java diferencia los métodos sobrecargados con base en el número y tipo de argumentos que tiene el método y no por el tipo que devuelve.
Tambien existe la sobrecarga de constructores: Cuando en una clase existen constructores múltiples, se dice que hay sobrecarga de constructores.
La firma de un método es la combinación del tipo de dato que regresa, su nombre y su lista de argumentos.
La sobrecarga de métodos es la creación de varios métodos con el mismo nombre pero con diferentes firmas y definiciones. Java utiliza el número y tipo de argumentos para seleccionar cuál definición de método ejecutar.
Java diferencia los métodos sobrecargados con base en el número y tipo de argumentos que tiene el método y no por el tipo que devuelve.
Tambien existe la sobrecarga de constructores: Cuando en una clase existen constructores múltiples, se dice que hay sobrecarga de constructores.
Ejemplo
/* Métodos sobrecargados */
int calculaSuma(int x, int y, int z){
...
}
int calculaSuma(double x, double y, double z){
...
}
/* Error: estos métodos no están sobrecargados */
int calculaSuma(int x, int y, int z){
...
}
double calculaSuma(int x, int y, int z){
...
}
Ejemplo
/* Usuario4.java */
class Usuario4
{
String nombre;
int edad;
String direccion;
/* El constructor de la clase Usuario4 esta sobrecargado */
Usuario4( )
{
nombre = null;
edad = 0;
direccion = null;
}
Usuario4(String nombre, int edad, String direccion)
{
this.nombre = nombre;
this.edad = edad;
this.direccion = direccion;
}
Usuario4(Usuario4 usr)
{
nombre = usr.getNombre();
edad = usr.getEdad();
direccion = usr.getDireccion();
}
void setNombre(String n)
{
nombre = n;
}
String getNombre()
{
return nombre;
}
/* El metodo setEdad() está sobrecargado */
void setEdad(int e)
{
edad = e;
}
void setEdad(float e)
{
edad = (int)e;
}
int getEdad()
{
return edad;
}
void setDireccion(String d)
{
direccion = d;
}
String getDireccion()
{
return direccion;
}
}
Ejemplo
/* ProgUsuario4.java */
class ProgUsuario4
{
void imprimeUsuario(Usuario4 usr)
{
// usr.nombre equivale en este caso a usr.getNombre()
System.out.println("\nNombre: " + usr.nombre );
System.out.println("Edad: " + usr.getEdad() );
System.out.println("Direccion: " + usr.getDireccion() +"\n");
}
public static void main(String args[])
{
ProgUsuario4 prog = new ProgUsuario4( );
/* Se declaran dos objetos de la clase Usuario4 */
Usuario4 usr1,usr2;
/* Se utiliza el constructor por omisión */
usr1 = new Usuario4( );
prog.imprimeUsuario(usr1);
/* Se utiliza el segundo constructor de Usuario4 */
usr2 = new Usuario4("Eduardo",24,"Mi direccion");
prog.imprimeUsuario(usr2);
/* Se utiliza el tercer constructor de Usuario4 */
usr1 = new Usuario4(usr2);
usr1.setEdad(50);
usr2.setEdad(30.45f);
prog.imprimeUsuario(usr1);
prog.imprimeUsuario(usr2);
}
}
10.- Modificadores de acceso.
Los modificadores de acceso nos introducen al concepto de encapsulamiento. El encapsulamiento busca de alguna forma controlar el acceso a los datos que conforman un objeto o instancia, de este modo podríamos decir que una clase y por ende sus objetos que hacen uso de modificadores de acceso (especialmente privados) son objetos encapsulados.
Los modificadores de acceso permiten dar un nivel de seguridad mayor a nuestras aplicaciones restringiendo el acceso a diferentes atributos, métodos, constructores asegurándonos que el usuario deba seguir una "ruta" especificada por nosotros para acceder a la información.
Es muy posible que nuestras aplicaciones vayan a ser usadas por otros programadores o usuarios con cierto nivel de experiencia; haciendo uso de los modificadores de acceso podremos asegurarnos de que un valor no será modificado incorrectamente por parte de otro programador o usuario. Generalmente el acceso a los atributos se consigue por medio de los métodos get y set, pues es estrictamente necesario que los atributos de una clase sean privados.
Nota: Siempre se recomienda que los atributos de una clase sean privados y por tanto cada atributo debe tener sus propios métodos get y set para obtener y establecer respectivamente el valor del atributo.
Nota 2: Siempre que se use una clase de otro paquete, se debe importar usando import. Cuando dos clases se encuentran en el mismo paquete no es necesario hacer el import pero esto no significa que se pueda acceder a sus componentes directamente.
Veamos un poco en detalle cada uno de los modificadores de acceso
Modificador de acceso private
El modificador private en Java es el más restrictivo de todos, básicamente cualquier elemento de una clase que sea privado puede ser accedido únicamente por la misma clase por nada más. Es decir, si por ejemplo, un atributo es privado solo puede ser accedido por lo métodos o constructores de la misma clase. Ninguna otra clase sin importar la relación que tengan podrá tener acceso a ellos.
En el ejemplo anterior vemos lo que mencioné al comiendo, tenemos un atributo privado y permitimos el acceso a él únicamente por medio de los métodos de get y set, notemos que estos métodos son públicos y por tanto cualquiera puede accederlos. Lo realmente interesante con los métodos get y set es que nos permiten realizar cualquier operación como por ejemplo llevar una cuenta de la veces que se estableció el valor para el atributo permitiéndonos mantener nuestro sistema sin problemas. También debemos notar que debido a que los métodos get y set son propios de la clase no tienen problemas con acceder al atributo directamente.
El modificador por defecto (default)
Java nos da la opción de no usar un modificador de acceso y al no hacerlo, el elemento tendrá un acceso conocido como defaulto acceso por defecto que permite que tanto la propia clase como las clases del mismo paquete accedan a dichos componentes (de aquí la importancia de declararle siempre un paquete a nuestras clases).
Modificador de acceso protected
El modificador de acceso protected nos permite acceso a los componentes con dicho modificador desde la misma clase, clases del mismo paquete y clases que hereden de ella (incluso en diferentes paquetes). Veamos:
Modificador public
El modificador de acceso public es el más permisivo de todos, básicamente public es lo contrario a private en todos los aspectos (lógicamente), esto quiere decir que si un componente de una clase es public, tendremos acceso a él desde cualquier clase o instancia sin importar el paquete o procedencia de ésta.
A continuación y ya para finalizar, pondré una pequeña tabla que resume el funcionamiento de los modificadores de acceso en Java.
PANCHITO
Comentarios
Publicar un comentario