Programación Orientada a Objetos
POO
Introducción a la POO
Contenido
-
Introducción a Programación Orientada a Objetos
-
Clases
-
Objetos
-
UML
-
Definición de clases en Java
Introducción a Programación Orientada a Objetos
- Paradigma de programación.
- Abstracción de la realidad.
- Diferente del paradigma procedimental.
- Formalización de los Tipos Abstractos de Datos (TAD).
- Muchos lenguajes de programación lo soportan:
- Java
- Python
- C++
- C#
- Entre otros.
Objeto
Clase
Herencia
Polimorfismo
Abstracción
Encapsulamiento
Desarrollo de Software Orientado a Objetos
- Análisis:
- Analizar el problema, sistema o tarea.
- Identificar los objetos y las relaciones entre estos.
- Identificar requerimientos.
- Diseño:
- Convertir los requerimientos en especificaciones para la implementación.
- Definir clases, objetos y comportamientos.
- Implementación: Convertir el diseño en un programa funcional.
Análisis
Diseño
Implementación
Ejemplo de requerimientos
- Buscar un libro.
- Buscar un producto.
- Ver recomendaciones.
- Cargar un documento.
- Inscribir una asignatura.
- Consultar la información de una persona.
Clase
- Abstracta.
- Conjunto de objetos que comparten una estructura bien definida.
- No representa a una entidad individual.
- Es definida dependiendo de las necesidades (requerimientos) del problema.
- Cualquier cosa se puede modelar como una clase.
Clase Carro

Objeto
- Concreto.
- Concepto, abstracción o cosa con límites bien definidos.
- Representa una entidad individual del conjunto de elementos que la clase define.
- Es una colección de datos con comportamientos asociados.
- Son instanciados a partir de una clase.
Objeto



Rayo Mcqueen
Tesla
Audi
Atributos
- Son datos que representan las características individuales de un objeto.
- En la clase se define un conjunto de atributos que son parte de todos los objetos de dicha clase.
- Cada objeto puede tener distintos valores en sus atributos.
- Corresponden a un tipo de dato específico:
- Genéricos: entero, float, string, booleano, byte.
- Colecciones: matrices, listas, tuplas, diccionarios, arboles, grafos.
- Otras Clases específicas de la aplicación
Un objeto puede tener infinitos atributos, pero no todos son relevantes para un problema dado
Atributos
Clase Carro

Objeto


Tesla
Audi
color: string;
modelo: int;
precio_euros: float;
tieneGPS: boolean;
color = blanco;
modelo = 2022;
precio_euros = 100000;
tieneGPS = true;
color = rojo;
modelo = 2024;
precio_euros = 90000;
tieneGPS = false;
Métodos
- Describen el comportamiento de los objetos.
- Son definidos dentro de la clase.
- A nivel de programación, son funciones que: tienen acceso a los atributos del objeto, pueden admitir parámetros y retornar valores.
Diferentes objetos de una misma clase pueden reaccionar de distintas maneras a la ejecución de un método
Métodos
Clase Carro

- encender();
- actualizarPrecio(double nuevoPrecio);
- activarAlarma();
- obtenerKilometraje();
- recargarCombustible(double litros);
- acelerar();
Ejemplo

UML
- Lenguaje unificado de modelado (Unified Modeling Language).
- Usado para describir modelos de sistemas.
- En POO, uno de los diagramas más usados son los Diagramas de Clases que:
- Describen las Clases, sus Atributos y sus Métodos.
- Describen Relaciones entre clases.

Tipos de relaciones:
- Asociación
- Agregación
- Herencia
- Multiplicidad
- Encapsulamiento
UML Definición de clases
- Cada clase se representa con un rectángulo dividido en tres secciones:
- La primera sección contiene el nombre de la clase
- La segunda sección contiene los atributos de la clase.
- La tercera sección contiene los métodos de la clase.
- No es necesario que las dos últimas secciones se utilicen.


Definicion de clase JAVA
public class Carro {
// Atributos
public String color;
public int modelo;
public float precio_euros;
public boolean tieneGPS;
// Constructor
public Carro(String color, int modelo, float precio_euros, boolean tieneGPS) {
this.color = color;
this.modelo = modelo;
this.precio_euros = precio_euros;
this.tieneGPS = tieneGPS;
}
// Métodos
public void encender() {
// Implementación del método encender
}
public void actualizarPrecio(double nuevoPrecio) {
// Implementación del método actualizarPrecio
}
public void activarAlarma() {
// Implementación del método activarAlarma
}
public double obtenerKilometraje() {
// Implementación del método obtenerKilometraje
}
public void recargarCombustible(double litros) {
// Implementación del método recargarCombustible
}
public void acelerar() {
// Implementación del método acelerar
}
}
Encapsulamiento y relaciones entre clases
Contenido
-
Encapsulamiento
-
Multiplicidad
-
Relaciones entre clases
Encapsulamiento
- El paradigma de programación procedimental tiene poca
protección de los datos- Las variables globales de un programa pueden ser accedidas y
alteradas por cualquier procedimiento del programa.
- Las variables globales de un programa pueden ser accedidas y
- El encapsulamiento hace referencia a ocultar los detalles
de implementación internos del objeto (atributos y
métodos) a los demás.- Cada objeto es dueño único de su información.
- Puede definir parámetros de acceso.
- Permite definir la interfaz pública de un objeto.

Encapsulamiento
Niveles de acceso o visibilidad
- Público: Se tiene acceso a los atributos o métodos sin restricción alguna. En UML se representa con el símbolo ‘ + ’.
- Privado: Ninguna clase externa puede acceder y mucho menos modificar los atributos o los métodos de esta clase. En UML se representa con el símbolo ‘ - ’.
- Protegido: Sólo las clases hijas tienen acceso a los atributos o métodos definidos en la clase padre. En UML se representa con el símbolo ‘ # ’.

Encapsulamiento en Java
public class MyClass {
// Atributos con diferentes niveles de acceso
public int x;
protected int y;
private int z;
// Constructor
public MyClass(int x, int y, int z) {
this.x = x;
this.y = y;
this.z = z;
}
// Método público
public void publicMethod() {
// Do something
}
// Método protegido
protected void protectedMethod() {
// Do something
}
// Método privado
private void privateMethod() {
// Do something
}
}
Encapsulamiento
- Para acceder a atributos privados es necesario usar métodos públicos.
- Estos métodos son conocidos como getters y setters:
// Getter
public type getAttribute() {
if (validationCondition) {
return this.attribute;
}
return null;
}
// Setter
public void setAttribute(type newValue) {
if (validationCondition) {
this.attribute = newValue;
}
}
Multiplicidad
Determina cuántos objetos de cada tipo intervienen en una relación
Indicador | Significado |
---|---|
0..1 | Cero o uno |
1 | Solo uno |
0..* | Cero o más |
1..* | Uno o más |
n | Solo n (n > 1) |
0..n | Cero a n (n > 1) |
1..n | Uno a n (n > 1) |
Multiplicidad

Asociaciones
Asociación bidireccional
- Conexión entre dos clases donde ambas se referencia mutuamente.
- Un objeto de una clase conoce a un objeto de la otra clase, y viceversa.
- Los elementos de ambas clases pueden existir de manera independiente.
- Los elementos de ambas clases son conscientes de la relación entre ellos.



Asociaciones
Asociación unidireccional
- Una clase conoce a otra clase, pero no al revés.
- Solo una de las clases tiene una referencia a la otra, y la relación NO es recíproca.
- La relación de las clases es en una dirección.
- Los elementos de ambas clases pueden existir de manera independiente.
- Sólo los elementos de una clase son conscientes de la relación entre ellos.



Asociaciones
Asociación reflexiva
- Una clase está asociada consigo misma.
- Un objeto de una clase se relaciona con otro objeto de la misma clase.
- Los objetos tienen una relación jerárquica, de dependencia o de agrupación entre sí.
- Una clase puede estar relacionada con otras instancias del mismo tipo.


Agregación
Agregación básica
- Una clase (el todo) contiene o está compuesta por otra clase.
Los elementos de ambas clases pueden existir de manera independiente. - Una clase se compone / contiene / posee / construye a partir de instancias de otra clase.
- Estas instancias no son parte fundamental de la clase, pero influyen en su funcionamiento.



Agregación
Agregación de composición
- Representa una asociación fuerte entre dos clases.
- Una clase (el todo) está compuesta por otra clase (la parte)
- Una clase se compone / contiene / posee / construye a partir de instancias de otra clase.
- Estas instancias son parte fundamental de la clase.
- Los objetos de la clase relacionada no pueden existir sin el objeto de la clase compuesta.



Ejemplo

Ejercicios
- Diseñe un diagrama UML para modelar un juego de ajedrez. Debe usar mínimo 3 de las relaciones mencionadas previamente
- Diseñe un diagrama UML para modelar el registro de materias en la universidad.
Herencia y Polimorfismo
Contenido
-
Herencia
-
Básica
-
Múltiple
-
-
Polimorfismo
-
Interno
-
Sobrecarga de métodos
-
-
Externo
-
Sobreescritura de métodos
-
Referencias múltiples
-
-
Herencia
- Una clase puede ser demasiado general para describir la naturaleza de todos los objetos que representa.
- Algunos objetos presentan atributos y comportamientos diferentes.
- Podemos pensar que debemos crear una clase para cada uno de ellos.
- Si se tienen mútiples clases con varios elementos en común:
- Genera repetición de código.
- Alto costo de mantenimiento.
- El cambio se debe repetir en cada copia del código.

Herencia básica
- Los aspectos comunes de varias clases se pueden concentrar en una única clase de “mayor nivel” que las agrupe, conocida como la clase padre.
- Las clases derivadas tendrán los atributos y los métodos de la clase padre, y adicionalmente podrá definir sus propios métodos y atributos.
- Al instanciar un objeto de una clase derivada es necesario instanciar los atributos del padre.
- Para instanciar estos atributos se utiliza el super, que generalmente referencia a la clase padre.
Herencia básica
// Clase padre
class Animal {
protected String nombre;
protected int edad;
public Animal(String nombre, int edad) {
this.nombre = nombre;
this.edad = edad;
}
public void hacerSonido() {
System.out.println("El animal hace un sonido");
}
}
// Clase derivada (hija)
class Perro extends Animal {
private String raza;
public Perro(String nombre, int edad, String raza) {
super(nombre, edad); // Llama atributos del padre
this.raza = raza;
}
@Override
public void hacerSonido() {
System.out.println("¡Guau!");
}
}
Herencia básica

Representación de la herencia en UML: Donde Clase1 es la clase padre y Clase2 es la clase hija o clase derivada.

La clase hija en UML no debe ser escrita con los atributos o métodos que toma del padre. Solo se escriben nuevos atributos, nuevos métodos o métodos que fueron sobreescritos o modificados.
Herencia multinivel
- También es posible tener múltiples niveles de herencia, es decir una clase derivada que a su vez puede ser una clase padre
- Son conocidas como herencia multinivel.
- En Java todas las clases extienden de la clase Object.


Herencia múltiple
- Una clase puede heredar de múltiples clases.
- Esto genera algunos problemas:
- Ambas clases padre implementen un mismo método con diferente funcionalidad.
- Problema del diamante.
- Algunos lenguajes de programación no lo soportan, pero esto puede solucionarse con el uso de interfaces.

Polimorfismo
Es uno de los grandes aportes de la programación orientada a objetos.
Definiciones:
- La capacidad de un método o una clase de poder asumir varias formas.
- La capacidad de tratar una clase de forma diferente, dependiendo de la subclase que se implemente.
- La capacidad de producir comportamientos diferentes en función de la subclase que se esté utilizando, sin tener que saber explícitamente cuál es la subclase en realidad.
Polimorfismo
Polimorfismo Interno - Sobrecarga de métodos
- Dentro de una clase se pueden tener varios métodos con el mismo nombre.
- Estos se distinguen por los diferentes conjuntos o permutaciones (en cuanto al tipo de datos) de los parámetros de entrada.
public class Calculadora {
public int sumar(int a, int b) {
return a + b;
}
public int sumar(int a, int b, int c) {
return a + b + c;
}
public double sumar(double a, double b) {
return a + b;
}
public String sumar(String a, String b) {
return a + b;
}
}

Polimorfismo
Polimorfismo Externo - Sobreescritura de métodos
- Cuando una clase hija quiere reescribir el método heredado de su clase padre.
- El nombre del método a reescribir debe ser exactamente igual que el del padre.
// Clase padre
class Instrumento {
public void tocar() {
System.out.println("Tocando un instrumento");
}
}
// Clase hija
class Guitarra extends Instrumento {
@Override
public void tocar() {
System.out.println("Tocando la guitarra con las cuerdas");
}
}
Instrumento obj1 = new Instrumento();
obj1.tocar();
>> Tocando un instrumento
Guitarra obj2 = new Guitarra();
obj2.tocar();
>> Tocando la guitarra con las cuerdas
Polimorfismo
Polimorfismo Externo - Múltiple referencia
Un objeto puede ser referenciado de múltiples maneras:
- La clase base (Object).
- Su propia clase.
- Su clase padre.
- Sus interfaces.
// Clase padre
class Instrumento {
public void tocar() {
System.out.println("Tocando un instrumento");
}
}
// Clase hija
class Guitarra extends Instrumento {
@Override
public void tocar() {
System.out.println("Tocando la guitarra con las cuerdas");
}
}
Object obj = new Guitarra();
Instrumento obj = new Guitarra();
Guitarra obj = new Guitarra();
Interfaces y Clases Abstractas
Contenido
-
Clases abstractas
-
Herencia abstracta
-
-
Interfaces
-
Otros modificadores
-
Estático (static)
-
Final
-
-
Enumeraciones
Clases abstractas
- Si la clase define objetos muy genéricos que no existen en la realidad (o en el sistema de información), se puede considerar una clase abstracta.
- Son clases que no pueden ser instanciadas.
- Una clase que incluye al menos un método abstracto es una clase abstracta.
- De las clases abstractas se pueden derivar clases concretas.
public abstract class FiguraGeometrica {
protected String color;
//Constructor
public Figura(String color) {
this.color = color;
}
//Métodos abtractos
public abstract double area();
public abstract double perimetro();
//Método no abstracto
public String getColor() {
return color;
}
}

Lo abstracto esta en cursiva(Italic)
Herencia abstracta
- Una relación de herencia es abstracta cuando la clase padre es una clase abstracta.
- Las clases hijas deben:
- Instanciar los atributos de la clase padre mediante el super.
- Definir (sobrescribir) los métodos abstractos de la clase padre.
- La clase abstracta puede ser utilizada para referenciar a un objeto concreto de una de sus clases hijas (Polimorfismo externo).
public class Rectangulo extends FiguraGeometrica {
private double base;
private double altura;
public Rectangulo(String color, double base, double altura) {
super(color);
this.base = base;
this.altura = altura;
}
@Override
public double area() {
return base * altura;
}
@Override
public double perimetro() {
return 2 * (base + altura);
}
}

Interfaces
- Una interfaz contiene:
- Conjunto de servicios que deben ser exhibidos por una clase (Varios métodos abstractos), solo se define nombre, salidas y entradas. No tiene código asociado.
- Constantes.
- Si una clase implementa una interfaz, debe definir el código de los métodos enumerados en la interfaz.
- Una clase puede implementar varias interfaces.
- Las interfaces permiten que clases diferentes puedan compartir un mismo conjunto de métodos, aunque estas clases no estén relacionadas entre sí.
Interfaces
// Definición de la interfaz
public interface Sonido {
public void hacerSonido();
public void ajustarVolumen(int nivel);
}
// Clase que implementa la interfaz
public class Guitarra implements Sonido {
private String marca;
private int volumen;
public Guitarra(String marca) {
this.marca = marca;
this.volumen = 5; // volumen por defecto
}
@Override
public void hacerSonido() {
System.out.println("La guitarra " + marca + " hace notas musicales");
}
@Override
public void ajustarVolumen(int nivel) {
this.volumen = nivel;
System.out.println("Volumen ajustado a: " + nivel);
}
}
Ejemplo
Interfaces
public class Despertador implements Sonido {
private String hora;
private int volumen;
public Despertador(String hora) {
this.hora = hora;
this.volumen = 10;
}
@Override
public void hacerSonido() {
System.out.println("El despertador hace RING RING a las " + hora);
}
@Override
public void ajustarVolumen(int nivel) {
this.volumen = nivel;
System.out.println("Alarma ajustada a volumen: " + nivel);
}
}
Ejemplo

Otros modificadores
Estático(static)
- Este modificador se utiliza para definir que el método o atributo NO depende de una instancia sino de una clase:
- El método/atributo puede ser invocado sin necesidad de una instancia de la clase.
public class MyClass {
public static int x = 5;
public static int add(int value) {
return value + x;
}
}
System.out.println(MyClass.x);
>> 5
System.out.println(MyClass.add(18));
>> 25
Otros modificadores
Final
- Este modificador se utiliza para definir que el valor de un atributo NO va a cambiar después de ser inicializado
- Usualmente representan constantes.
private final String name;
public static final double PI = 3.1415;
- Se puede utilizar para definir que una clase NO puede tener clases hijas.
public final class Student extends Person{...}
Enumeraciones
- Una enumeración es una clase "especial" que representa un grupo de constantes.
- Limitan la creación de objetos a los especificados explícitamente en la implementación de la clase.
- Tienen métodos heredados de su clase padre Enum.
- En caso de tener constructor, debe ser privado o protegido para que no se puedan crear nuevos objetos.
- Se pueden definir dentro de una clase.
public enum DiaSemana {
LUNES,
MARTES,
MIERCOLES,
JUEVES,
VIERNES,
SABADO,
DOMINGO
}

Enumeraciones
public enum TipoVehiculo {
COCHE(4),
MOTO(2),
CAMION(6);
private final int numRuedas;
// Constructor privado
private TipoVehiculo(int numRuedas) {
this.numRuedas = numRuedas;
}
public int getNumRuedas() {
return numRuedas;
}
}
Otro ejemplo
Ventajas
- Tipo seguro: no puedes asignar valores que no estén definidos
- Conjunto cerrado de valores
- Pueden tener métodos y atributos
- Útiles para representar estados, tipos o categorías fijas
- Mejoran la legibilidad del código
Casos comunes de uso
- Estados de un proceso (INICIADO, EN_PROCESO, FINALIZADO)
- Días de la semana
- Meses del año
- Tipos de usuario (ADMIN, USUARIO, INVITADO)
- Categorías de productos
- Niveles de acceso
Pruebas (Testing)
Contenido
-
Pruebas (Testing)
-
Principios del testing
-
Tipos de pruebas
-
-
Plan de pruebas
-
Introducción a pruebas unitarias en Java
Pruebas
Es el proceso de evaluar y verificar que un producto o aplicación de software lleve a cabo su propósito correctamente.
Beneficios de las pruebas:
- Prevención de errores.
- Reducción de los costos de desarrollo.
- Mejora del rendimiento de la aplicación

Pruebas
Principios:
- El testing sirve para demostrar defectos
- No es posible realizar testing de software exhaustivo
- Necesidad de realizar pruebas tempranas
- Agrupación de defectos.
- Paradoja del pesticida.
- Se debe tener en cuenta el contexto.
- La ausencia de errores es una falacia.

Pruebas
Tipos de pruebas:
- Pruebas unitarias
- Pruebas de integración
- Pruebas funcionales
- Pruebas de extremo a extremo
- Pruebas de aceptación
- Pruebas de rendimiento.
- Pruebas de humo

Pruebas
Pruebas unitarias
- Pruebas de muy bajo nivel.
- Se realizan cerca de la fuente de la aplicación.
- Consisten en probar métodos y funciones individuales de:
1) Clases
2) Componentes
3) Módulos - Son las primeras que se deben realizar durante todo el proceso de desarrollo.

Pruebas
Pruebas de integración
- Se encargan de verificar que los distintos módulos o servicios utilizados por la aplicación funcionen bien en conjunto, es decir se integren de la manera correcta.
- Los sistemas que interactúan entre si pueden ser internos o externos

Pruebas
Pruebas funcionales
- Se centran en los requisitos empresariales de una aplicación.
- Solo verifican el resultado de una acción.
- No comprueban los estados intermedios del sistema al realizar la acción.
- Son consideradas pruebas de caja negra, donde solo se controla la entrada y salida mas no se ve el proceso interno.

Pruebas
Pruebas de extremo a extremo
- Replican el comportamiento que puede tomar un usuario con el software en un entorno de aplicación completo.
- Verifican que diversos flujos de usuario funcionen de manera correspondiente.
- Validan que los flujos críticos del sistema funcionan correctamente.

Pruebas
Pruebas de aceptación
- Son pruebas formales que verifican si un sistema satisface los requisitos empresariales. Se deben definir los criterios de aceptación con anterioridad.
- Requieren que se esté ejecutando toda la aplicación durante las pruebas. Se centran en replicar conductas de los usuarios.
- Se puede medir el rendimiento del sistema y rechazar cambios si no se han cumplido algunos objetivos.

Pruebas
Pruebas de rendimiento
- Evalúan el rendimiento de un sistema con una carga de trabajo definida.
- Ayudan a medir la fiabilidad, velocidad, escalabilidad y la capacidad de respuesta de una aplicación
- Cumplir con los requisitos de rendimiento.
- Localizar cuellos de botella.
- Medir la estabilidad durante los picos de tráfico.

Pruebas
Pruebas de humo
- Pruebas básicas que sirven para comprobar el funcionamiento básico de la aplicación.
- Su objetivo es ofrecer la seguridad de que las principales funciones del sistema se ejecuten según lo previsto.
- Determinan si la aplicación está preparada para ser sometida por pruebas más exhaustivas.
- Si no se superan estas pruebas no se programan pruebas más complejas.

Plan de pruebas
- Tiene como objetivo orientar el esfuerzo de pruebas, definiendo las pruebas más importantes según sea el caso.
- Se sugiere utilizar las pruebas establecidas por el ISTQB(International Software Testing Qualifications Board).
- Se debe tener en cuenta:
- Objetivos de negocio que tiene que cumplir el software.
- Calendario del proyecto.
- Metodología usada para del desarrollo.

Plan de pruebas

Plan de pruebas

Plan de pruebas

Plan de pruebas

Introducción a pruebas unitarias en Java
- Para realizar pruebas unitarias en Java se utiliza la librería
junit.
Es una librería externa que debe ser descargada y añadida al proyecto. - Las librerías deben ser incluidas en el apartado de Test Libraries del proyecto.
- Una prueba cuenta con 3 partes:
- Given: Condiciones iniciales de la prueba.
- When: Ejecución de la prueba.
- Then: Verificación de los valores de prueba.
public class MyClass {
private int number;
public MyClass(int number) {
this.number = number;
}
public int add(int value) {
return this.number + value;
}
}
import static org.junit.Assert.assertEquals;
import org.junit.Test;
public class MyClassTest {
@Test
public void testAdd() throws Throwable {
// Given
MyClass obj = new MyClass(5);
// When
int value = 12;
int result = obj.add(value);
// Then
assertEquals(17, result);
}
}
Programación Orientada a Objetos
By Sebastian David Ariza Coll
Programación Orientada a Objetos
- 60