Diseño Orientado a Objetos#

Objetivo#

Al finalizar esta clase, los estudiantes comprenderán los principios fundamentales del diseño orientado a objetos (OO), las propiedades clave que caracterizan este enfoque, y los mecanismos de herencia utilizados para crear jerarquías de clases en sistemas de software. Además, podrán aplicar estos conceptos en ejemplos prácticos usando Java.

1. Definición del Diseño Orientado a Objetos#

Concepto Básico#

El Diseño Orientado a Objetos (OO) es un enfoque de desarrollo de software que organiza el diseño del sistema en torno a «objetos,» que son instancias de «clases.» Estos objetos encapsulan datos y comportamientos relacionados, y se comunican entre sí mediante métodos.

Objetos#

../images/objects.png

Figura 28 Características de un objeto.#

../images/roles1.png

Figura 29 Comportamiento de los objetos.#

../images/roles.png

Figura 30 Ciclo de vida de los objetos.#

Clases#

../images/class.png

Figura 31 Ilustración de la definición de una clase.#

Historia y Evolución#

El diseño orientado a objetos surgió en la década de 1960 con lenguajes como Simula y Smalltalk, y se popularizó en los años 80 y 90 con lenguajes como C++ y Java. Hoy en día, es un enfoque fundamental en el desarrollo de software moderno.

Generaciones y Estructuras#

  • First-generation languages (1954–1958)

    • FORTRAN I    Mathematical expressions

    • ALGOL 58      Mathematical expressions

    • Flowmatic       Mathematical expressions

    • IPL V         Mathematical expressions

../images/topology1.png
  • Second-generation languages (1959–1961)

    • FORTRAN II    Subroutines, separate compilation

    • ALGOL 60     Block structure, data types

    • COBOL       Data description, file handling

    • Lisp        List processing, pointers, garbage collection

../images/topology2.png
  • Third-generation languages (1962–1970)

    • PL/1        FORTRAN + ALGOL + COBOL

    • ALGOL 68      Rigorous successor to ALGOL 60

    • Pascal       Simple successor to ALGOL 60

    • Simula       Classes, data abstraction

../images/topology3.png
  • The generation gap (1970–1980) Many different languages were invented, but few endured. However, the following are worth noting:

    • C           Efficient; small executables

    • FORTRAN 77     ANSI standardization

  • Object-orientation boom (1980–1990, but few languages survive)

    • Smalltalk 80       Pure object-oriented language

    • C++            Derived from C and Simula

    • Ada83           Strong typing; heavy Pascal influence

    • Eiffel           Derived from Ada and Simula

  • Emergence of frameworks (1990–today) Much language activity, revisions, and standardization have occurred, leading to programming frameworks.

    • Visual Basic       Eased development of the graphical user interface (GUI) for Windows applications

    • Java            Successor to Oak; designed for portability

    • Python           Object-oriented scripting language

    • J2EE           Java-based framework for enterprise computing

    • .NET           Microsoft’s object-based framework

    • Visual C#         Java competitor for the Microsoft .NET Framework

    • Visual Basic .NET   Visual Basic for the Microsoft .NET Framework

../images/topology4.png
../images/topology5.png

Importancia en el Desarrollo de Software#

El enfoque orientado a objetos facilita el diseño de sistemas complejos al promover la reutilización de código, la modularidad y la claridad en la estructura del software. Este enfoque es crucial para construir sistemas escalables, mantenibles y fáciles de entender.

Ventajas del Diseño OO:#

  • Modularidad: Dividir un sistema en objetos ayuda a gestionar la complejidad y facilita el mantenimiento.

  • Reutilización: Las clases y objetos pueden ser reutilizados en diferentes partes del sistema o en otros proyectos.

  • Flexibilidad: El diseño OO permite modificaciones y ampliaciones sin afectar la estructura completa del sistema.

2. Propiedades del Diseño Orientado a Objetos#

Encapsulamiento#

El encapsulamiento es el proceso de ocultar los detalles internos de un objeto y exponer solo lo necesario a través de una interfaz pública. Esto se logra mediante el uso de modificadores de acceso (público, privado, protegido) en las clases de Java.

../images/encapsulation.png

Figura 32 Ilustración.#

Abstracción#

La abstracción permite a los desarrolladores centrarse en lo esencial, ignorando los detalles complejos que no son relevantes en un contexto particular. Las clases abstractas e interfaces en Java ayudan a lograr la abstracción.

../images/abstraction0.png

Figura 33 Ilustración.#

Modularidad#

La modularidad divide el software en partes manejables, llamadas «módulos» o «clases», que pueden desarrollarse, probarse y mantener de forma independiente.

../images/modularity.png

Figura 34 Ilustración.#

Polimorfismo#

El polimorfismo permite que un objeto se comporte de diferentes maneras según el contexto. En Java, se implementa mediante la sobrecarga de métodos y la implementación de interfaces.

3. Mecanismos de Herencia en el Diseño Orientado a Objetos#

Definición y Propósito de la Herencia#

La herencia es un mecanismo que permite que una clase (subclase o clase hija) herede atributos y métodos de otra clase (superclase o clase padre). Esto facilita la reutilización de código y la creación de jerarquías de clases que reflejan relaciones «es-un» (is-a) en el mundo real.

../images/subclass.png

Figura 35 Ilustración de la herencia.#

../images/abstraction.png

Figura 36 Ilustración de la jerarquia.#

Tipos de Herencia#

  • Herencia Simple: Una clase hereda de una única superclase.

  • Herencia Múltiple: Una clase hereda de más de una superclase. (No soportada directamente en Java, pero se puede simular mediante interfaces).

  • Herencia Jerárquica: Varias clases heredan de una misma superclase.

  • Herencia Multinivel: Una clase hereda de una subclase que a su vez es una subclase de otra clase.

Implementación de la Herencia en Java#

class Vehiculo {
    String marca;
    int año;

    public Vehiculo(String marca, int año) {
        this.marca = marca;
        this.año = año;
    }

    public void encender() {
        System.out.println("El vehículo está encendido.");
    }
}

class Coche extends Vehiculo {
    int puertas;

    public Coche(String marca, int año, int puertas) {
        super(marca, año);
        this.puertas = puertas;
    }

    @Override
    public void encender() {
        System.out.println("El coche está encendido.");
    }
}

Problemas y Buenas Prácticas en la Herencia#

  • Problemas de Herencia Múltiple: Java no soporta herencia múltiple para evitar la ambigüedad que podría surgir.

  • Uso Juicioso de la Herencia: Se recomienda usar la herencia solo cuando hay una verdadera relación «es-un» entre las clases. De lo contrario, la composición podría ser más apropiada.

4. Ejemplo Práctico en Java#

Modelado de un Sistema de Gestión de Vehículos#

  • Crear clases Vehiculo, Coche, Moto y Camion.

  • Implementar características comunes como marca, año, y métodos como encender() en la clase Vehiculo.

  • Extender Vehiculo para que Coche, Moto y Camion hereden sus atributos y métodos.

  • Utilizar polimorfismo para implementar métodos como encender() de manera diferente en cada subclase.

Implementación del Ejemplo en Java#

class Vehiculo {
    protected String marca;
    protected int año;

    public Vehiculo(String marca, int año) {
        this.marca = marca;
        this.año = año;
    }

    public void encender() {
        System.out.println("El vehículo está encendido.");
    }
}

class Coche extends Vehiculo {
    public Coche(String marca, int año) {
        super(marca, año);
    }

    @Override
    public void encender() {
        System.out.println("El coche está encendido.");
    }
}

class Moto extends Vehiculo {
    public Moto(String marca, int año) {
        super(marca, año);
    }

    @Override
    public void encender() {
        System.out.println("La moto está encendida.");
    }
}

public class TestVehiculos {
    public static void main(String[] args) {
        Vehiculo miCoche = new Coche("Toyota", 2020);
        Vehiculo miMoto = new Moto("Harley", 2021);

        miCoche.encender();
        miMoto.encender();
    }
}

5. Conclusión#

El diseño orientado a objetos es una herramienta poderosa para crear sistemas de software robustos y mantenibles. A través de la encapsulación, la abstracción, la modularidad y el polimorfismo, los desarrolladores pueden construir soluciones flexibles y escalables. La herencia, cuando se usa adecuadamente, permite la reutilización efectiva del código y la creación de estructuras jerárquicas que reflejan las relaciones naturales en el sistema. Sin embargo, es importante usar la herencia con cuidado y considerar alternativas como la composición cuando sea más apropiado. El dominio de estos conceptos permitirá a los estudiantes diseñar e implementar software de alta calidad en Java.

Recursos Adicionales#