Programación orientada a objetos en Java

Índice
La programación orientada a objetos (POO) ... 2 Un ejemplo: una clase Punto ... 4 Programas orientados a objetos ... 7 Otro ejemplo: una clase Circulo ... 9 Encadenamiento de mensajes ... 10 Los atributos ... 12 Los objetos ... 13 Herencia ... 14 Herencia y pasos de mensajes ... 20 Polimorfismo y vinculación dinámica ... 21 Relaciones entre clases ... 25 POO y reutilización ... 26

Curso de Java

Programación orientada a objetos en Java
El lenguaje Java — Tema 3 — POO en Java

...
Curso de Java Luis Hernández Yáñez Carlos Cervigón Rückauer Tema 3 – POO en Java - 1

La programación orientada a objetos (POO)
Una nueva forma de ver las cosas
Se puede decir que la POO es la programación con TAD (tipos abstractos de datos) más una serie de mecanismos adicionales. Dejando aparte esos otros mecanismos, podemos establecer un paralelismo entre los TAD y la POO: Programación con TAD Definición Estado Comportamiento Ejemplares TAD Datos Operaciones Variables POO Clase Atributos Métodos Objetos

La programación orientada a objetos (POO)
La definición de los ejemplares (estado y comportamiento) se encuentra en la clase. Las clases encapsulan código y datos. Los ejemplares de las clases son los objetos. La clase define atributos (datos) y métodos (operaciones). Vista externa de una clase (su interfaz): Nombre y forma de uso de sus métodos. Los atributos han de ocultarse (ocultamiento de la información). Cada objeto (ejemplar) contiene su propio conjunto de atributos. Cada método declarado en la clase constituye un servicio que proporcionan todos los objetos de esa clase. Todos los objetos de una misma clase proporcionan los mismos servicios (tienen un mismo comportamiento).
Curso de Java Luis Hernández Yáñez Carlos Cervigón Rückauer Tema 3 – POO en Java - 3

Curso de Java

Luis Hernández Yáñez Carlos Cervigón Rückauer

Tema 3 – POO en Java - 2

Un ejemplo: una clase Punto
public class Punto { Nombre de la clase: Punto double _x; Atributos: _x _y double _y; Privados: accesibles public double x() { sólo en los métodos return _x; Métodos: } x() x(double) public double y() { y() y(double) return _y; print() } public void x(double d) { _x = d; } Todo lo que no es interfaz public void y(double d) { es implementación _y = d; } public void print() { System.out.print("(" + _x + "," + _y + ")"); } } Punto.java
Luis Hernández Yáñez Carlos Cervigón Rückauer Tema 3 – POO en Java - 4

Un ejemplo: una clase Punto
La clase Punto: Define dos atributos: _x e _y Cada ejemplar (objeto) tendrá sus propias coordenadas x e y. Define cinco métodos: x(), y(), x(double), y(double) y print(). Todos los objetos de la clase Punto proporcionan cinco servicios: x(), y(), x(double), y(double) y print(). Creación de ejemplares (objetos) de la clase Punto:
Punto p1 = new Punto(), p2 = new Punto();

I N T E R F A Z

p1 tiene sus propios valores _x e _y, distintos de los de p2. Cuando se quiere que un determinado objeto realice un determinado servicio (método), se le pasa un mensaje:
p1.y(12) p2.print()
Curso de Java

Paso del mensaje y() al objeto p1. Paso del mensaje print() al objeto p2.
Luis Hernández Yáñez Carlos Cervigón Rückauer Tema 3 – POO en Java - 5

Curso de Java

Un ejemplo: una clase Punto
Los objetos de una clase entienden tantos mensajes como métodos estén definidos en la clase (mismo comportamiento). A los objetos de clase Punto se les puede pasar cinco mensajes:
x() y() x(double) y(double) print()

Programas orientados a objetos
Un programa orientado a objetos está compuesto por: Un conjunto de clases que describen los objetos que maneja la aplicación. Un programa principal que pone en marcha el mecanismo de paso de mensajes: el método main().
public class PruebaPunto { public static void main(String[] args) { Punto unPunto = new Punto(); unPunto.x(2); Pasos de mensajes unPunto.y(7); unPunto.print(); System.out.println(); } }

Paso de mensajes:

objeto . mensaje (argumentos)
Cuando se pasa un mensaje a un objeto se busca en la clase un método que coincida con el mensaje (nombre y argumentos): Si se encuentra tal método, se ejecuta el código de ese método. Si no se encuentra tal método: el objeto no entiende el mensaje.
Curso de Java Luis Hernández Yáñez Carlos Cervigón Rückauer Tema 3 – POO en Java - 6 Curso de Java

PruebaPunto.java
Luis Hernández Yáñez Carlos Cervigón Rückauer Tema 3 – POO en Java - 7

Programas orientados a objetos
Cada paso de mensaje provoca la ejecución del correspondiente método definido en la clase del objeto receptor. El código del método puede ser: Una secuencia de instrucciones que no involucre objetos (programación basada en tipos estándar) Una secuencia de pasos de mensajes a otros objetos (normalmente a los objetos atributos) Una combinación de los dos casos anteriores (programación mixta o híbrida) Si la ejecución de un método no genera otros pasos de mensajes, el método se considera elemental. Si la ejecución de un método genera otros pasos de mensajes, se produce un encadenamiento de mensajes.
Luis Hernández Yáñez Carlos Cervigón Rückauer

Otro ejemplo: una clase Circulo
public class Circulo { Punto _centro; Atributo objeto de otra clase double _radio; public Punto centro() { return _centro; } public double radio() { return _radio; } public void centro(Punto p) { _centro = p; } public void radio(double r) { _radio = r; } Paso de mensaje public void print() { al objeto atributo System.out.print("["); _centro.print(); System.out.print("," + _radio + "]"); } Circulo.java }
Curso de Java Luis Hernández Yáñez Carlos Cervigón Rückauer Tema 3 – POO en Java - 9

Curso de Java

Tema 3 – POO en Java - 8

Encadenamiento de mensajes
Ejecución de un programa orientado a objetos El programa crea objetos y les pasa mensajes.
public class PruebaCirculo { public static void main(String[] args) { Punto unPunto = new Punto(); unPunto.x(2); unPunto.y(7); Circulo unCirculo = new Circulo(); unCirculo.centro(unPunto); unCirculo.radio(3); unCirculo.print(); System.out.println(); } }

Encadenamiento de mensajes
El encadenamiento de mensajes se produce cuando la ejecución de un método consiste en pasos de mensajes.
unCirculo.print()
El objeto unCirculo es de clase Circulo

public class Circulo { ... public void print() { System.out.print("["); _centro.print(); ... } El atributo _centro }
es un objeto de la clase Punto

public class Punto { ... public void print() { ... } }

Cada mensaje que se pasa provoca la ejecución del correspondiente método de la clase del objeto receptor.
Curso de Java Luis Hernández Yáñez Carlos Cervigón Rückauer

PruebaCirculo.java
Tema 3 – POO en Java - 10

El encadenamiento de mensajes termina en los métodos elementales (se vuelve del método sin que se produzcan otros pasos de mensaje).
Curso de Java Luis Hernández Yáñez Carlos Cervigón Rückauer Tema 3 – POO en Java - 11

Los atributos
Como hemos visto, los atributos pueden ser: Datos elementales (de tipos incorporados en el lenguaje). Ejemplares (objetos) de otras clases. Los objetos contienen objetos. Resulta habitual que las clases incluyan, entre otros, métodos accedentes y métodos mutadores para los distintos atributos: Accedentes – para obtener atributos: centro() y radio() en la clase Circulo x() e y() en la clase Punto. Mutadores – para establecer los atributos: centro(Punto) y radio(double) en la clase Circulo x(double) e y(double) en la clase Punto. Sin embargo, veremos que hay clases en las que no procede incluir accedentes y/o mutadores.
Curso de Java Luis Hernández Yáñez Carlos Cervigón Rückauer Tema 3 – POO en Java - 12

Los objetos
En los programas orientados a objetos se pueden distinguir distintos objetos, atendiendo a su existencia y su uso: Objetos globales: creados en el programa principal. Existen durante toda la ejecución del programa (una vez creados con new). Objetos atributos: objetos que son atributos de otros objetos. Existen independientemente de los objetos que los contienen. Objetos parámetros: reciben los argumentos de los métodos. Con objetos, parámetro y argumento se confunden. Se manejan directamente los objetos que se pasan (paso por referencia). Objetos locales: se crean en los métodos. Existen durante la ejecución del método en cuestión (una vez creados).
Luis Hernández Yáñez Carlos Cervigón Rückauer

Curso de Java

Tema 3 – POO en Java - 13

Herencia
La herencia es un mecanismo fundamental de la POO que no se encuentra en anteriores enfoques de programación. La herencia fomenta la reutilización. Supongamos que necesitamos una clase para elipses. Las elipses son básicamente círculos con otro radio más (por ejemplo, el radio mayor). Podemos entonces aprovechar la clase Circulo ya existente y hacer que la nueva clase que necesitamos herede las características (atributos y métodos) de aquella:
public class Elipse extends Circulo { ... Circulo

Herencia
Cuando hacemos que una nueva clase sea subclase de otra, la nueva clase automáticamente adopta (hereda) los atributos y los métodos que están definidos en la existente (superclase). Así, ahora la clase Elipse también tiene definidos dos atributos y cinco métodos. Atributos: _centro y _radio Métodos: centro(), radio(), centro(Punto), radio(double) y print() Dentro de la declaración propia de la subclase se describen las diferencias existentes respecto de la subclase: Nuevas características (atributos/métodos).
Elipse

Decimos que la clase Elipse hereda (es subclase) de la clase Circulo.
Curso de Java Luis Hernández Yáñez Carlos Cervigón Rückauer

Redefinición de características heredadas.
Luis Hernández Yáñez Carlos Cervigón Rückauer

Tema 3 – POO en Java - 14

Curso de Java

Tema 3 – POO en Java - 15

Herencia
Nuevas características: Nuevo atributo _radioMayor para el radio mayor de la elipse. (El atributo _radio heredado se considera el radio menor.) Accedente y mutador para el nuevo atributo (radioMayor() y radioMayor(double)).

Herencia
public class Elipse extends Circulo { double _radioMayor; public double radioMayor() { return _radioMayor; } public void radioMayor(double r) { _radioMayor = r; } public void print() { System.out.print("["); _centro.print(); System.out.print("," + _radio + "," + _radioMayor + "]"); } } Elipse.java
Curso de Java Luis Hernández Yáñez Carlos Cervigón Rückauer Tema 3 – POO en Java - 17

Redefinición de características: La información de las elipses no se muestra igual que la de los círculos, por lo que se debe redefinir el método print().

Curso de Java

Luis Hernández Yáñez Carlos Cervigón Rückauer

Tema 3 – POO en Java - 16

Herencia
Características de la nueva clase Elipse (subclase de Circulo): Atributos: _centro _radio _radioMayor Métodos: centro() radio() radioMayor() centro(Punto) radio(double) radioMayor(double) print() heredado heredado propio

Herencia
Las relaciones de herencia entre clases se pueden representar en forma de árbol (invertido), obteniéndose una representación gráfica de la jerarquía de clases:
ObjetoGrafico

heredado heredado propio heredado heredado propio propio (redefine el heredado)

Punto

Forma

Linea

Circulo

Cuadrado

Elipse

Rectangulo

Curso de Java

Luis Hernández Yáñez Carlos Cervigón Rückauer

Tema 3 – POO en Java - 18

Curso de Java

Luis Hernández Yáñez Carlos Cervigón Rückauer

Tema 3 – POO en Java - 19

Herencia y pasos de mensajes
La herencia modifica el mecanismo de paso de mensajes: Cuando a un objeto de una clase C se le pasa un mensaje M, se busca primero un método M en la clase C. 1. Si existe un método M en la clase C, se ejecuta ese método y termina el proceso. 2. Si en la clase C no hay ningún método M, se busca éste en la superclase de C. 3. Si en la superclase de C existe un método M, se ejecuta ese método y termina el proceso. 4. Si en la superclase de C no hay ningún método M, se busca en las superclases de la superclase hasta que o bien se encuentra y se ejecuta o no se encuentra en ninguna de las superclases, de forma que el objeto no entiende ese mensaje M.
Curso de Java Luis Hernández Yáñez Carlos Cervigón Rückauer Tema 3 – POO en Java - 20

Polimorfismo y vinculación dinámica
Identificadores y objetos Los objetos se manejan en los programas por medio de identificadores:
Circulo unCirculo; Punto unPunto;
Identificadores

Cuando se establecen relaciones de herencia entre clases, se sigue una regla de compatibilidad de objetos que dice que

un identificador declarado como de clase X puede hacer referencia a un objeto de la clase X o de cualquiera de sus subclases
Un Circulo puede ser un Circulo normal (sin dos radios) o una Elipse, pero una Elipse NO puede ser un Circulo normal (sin dos radios).
Esto puede resultar controvertido: un círculo se puede considerar una elipse con los dos radios iguales.
Curso de Java Luis Hernández Yáñez Carlos Cervigón Rückauer Tema 3 – POO en Java - 21

Polimorfismo y vinculación dinámica
De acuerdo con lo anterior, lo siguiente es válido:
Circulo unCirculo; Elipse unaElipse; // ... unCirculo = unaElipse;

Polimorfismo y vinculación dinámica
public class Polimorfismo { public static void main(String[] args) { Punto unPunto = new Punto(); unPunto.x(2); unPunto.y(7); Circulo unCirculo = new Circulo(); unCirculo.centro(unPunto); unCirculo.radio(1); Elipse unaElipse = new Elipse(); unaElipse.centro(unPunto); unaElipse.radio(3); unaElipse.radioMayor(4); Circulo c; c = unCirculo; // Ahora es un Circulo c.print(); System.out.println(); c = unaElipse; // Y ahora una Elipse c.print(); System.out.println(); } Polimorfismo.java }
Curso de Java Luis Hernández Yáñez Carlos Cervigón Rückauer Tema 3 – POO en Java - 23

La regla de compatibilidad de objetos nos lleva a otro mecanismo fundamental de la POO: el polimorfismo. El identificador c anterior puede hacer referencia a un objeto de la clase Circulo o a un objeto de la clase Elipse. El objeto al que haga referencia puede ser de dos formas distintas (de una de las dos clases) e incluso puede pasar de hacer referencia a un objeto con una forma (de una clase) a hacer referencia a un objeto con otra forma (de la otra clase). Es polimórfico.
Luis Hernández Yáñez Carlos Cervigón Rückauer

Curso de Java

Tema 3 – POO en Java - 22

Polimorfismo y vinculación dinámica
El polimorfismo nos lleva a otro mecanismo fundamental de la POO: la vinculación dinámica.
Circulo unCirculo; Elipse unaElipse; Circulo c; int opcion; // ... if(opcion == 1) c = unCirculo; else c = unaElipse; c.print();

Relaciones entre clases
En los programas orientados a objetos se establecen dos tipos de relaciones entre las clases: Relación de herencia: una clase es descendiente de otra clase. Relación de clientelismo: una clase hace uso de otra clase. (Por ejemplo, porque declara algún atributo como objeto de la otra clase.) Si en un programa se necesita una clase de una biblioteca, habrá que incluir esa clase junto con todas aquellas con las que tenga establecidas relaciones de herencia y clientelismo.

¿Qué método print() se ejecutará? ¿El de la clase Circulo o el de la clase Elipse? No podemos saberlo hasta que se ejecute el programa. El mensaje print() no se vincula con el método print() correspondiente hasta que le llegue el momento de ejecutarse. La vinculación entre mensajes y métodos se lleva a cabo en tiempo de ejecución ⇒ vinculación dinámica.
Curso de Java Luis Hernández Yáñez Carlos Cervigón Rückauer Tema 3 – POO en Java - 24

Curso de Java

Luis Hernández Yáñez Carlos Cervigón Rückauer

Tema 3 – POO en Java - 25

POO y reutilización
Una de las características más relevantes de la POO es que fomenta la reutilización del software, reduciendo significativamente los costes del desarrollo de programas. Las clases, por sí mismas, son módulos de programa reutilizables: Siempre que se necesite una determinada funcionalidad y ésta pueda ser proporcionada por una clase existente, se usará ésa. Pero la POO lleva la reutilización a otro nivel: ¿Qué pasa si se necesita una funcionalidad que ninguna clase existente proporciona tal cual, pero que es parecida a la que proporciona alguna clase existente? La herencia es la clave en este caso: se crea una nueva clase a partir de esa cuya funcionalidad es parecida a la que se necesita. De esta forma, se reutiliza todo lo que es adecuado de esa clase y el desarrollo se centra únicamente en las diferencias.
Luis Hernández Yáñez Carlos Cervigón Rückauer

POO y reutilización
La reutilización debe tenerse siempre presente durante la programación orientada a objetos de un sistema. Siempre que se pueda usar una clase existente, obviamente se preferirá reutilizar la clase antes que crear otra nueva. Siempre que haya que crear una nueva clase (por no existir ninguna que resulte adecuada), se buscarán primero clases existentes que tengan bastantes similitudes con la que se ha de crear. Si se encuentra alguna con suficientes similitudes, se hará que la nueva clase sea subclase suya. De esta forma se aprovechan (reutilizan) las características ya desarrolladas en la clase existente.

¿Cómo de similar debe ser la clase que se necesita respecto de la clase ya existente?

Todas o casi todas las características deben ser adecuadas. Se necesitarán algunas más y/o cambiar algunas pocas. La experiencia aquí es la mejor ayuda.

Curso de Java

Tema 3 – POO en Java - 26

Curso de Java

Luis Hernández Yáñez Carlos Cervigón Rückauer

Tema 3 – POO en Java - 27