Object Oriented Paradigm

Los cuatro pilares de la POO y las relaciones entre objetos: dependencia, asociación, agregación, composición y herencia explicadas con ejemplos en Python.
POO
Python
Published

March 28, 2023

Pilares POO

  • Abstracción
  • Encapsulación
  • Herencia
  • Polimorfismo

Dependencia

  • Relación más básica y débil entre clases.
  • Cambios en la definición de una clase puede provocar modificaciones en otra.
  • Ocurre normalmente cuando utilizas nombres de clases concretas en tu código.
class Student:
    def remember(self):
        pass


class Course:
    def get_knowledge(self):
        pass


class Teacher:
    def __init__(self, student: Student):
        self.student = student

    def teach(self, course: Course):
        self.student.remember(
            course.get_knowledge()
        )

Si alguien cambia el método get_knowledge() de la clase Course (nombre, parámetros, etc.) nuestro código se va a romper.

Asociación

  • La asociación es una relación en la que un objeto utiliza o interactúa con otro.
  • La asociación puede verse como un tipo especializado de dependencia, en la que un objeto siempre tiene acceso a los objetos con los que interactúa, mientras que la dependencia simple no establece un vínculo permanente entre los objetos.
class Student:
    def remember(self):
        pass


class Course:
    def get_knowledge(self):
        pass


class Teacher:
    def __init__(self):
        self.student = Student()

    def teach(self, course: Course):
        self.student.remember(
            course.get_knowledge()
        )

La clase Student también es una dependencia ya que cuando se crea el objeto Teacher, se crea además un Student. La diferencia es que self.student va a estar accesible para cualquier método, no solo para teach.

Agregación

  • Tipo especializado de asociación que representa relaciones “uno a muchos”, “muchos a muchos” o “todo a parte” entre múltiples objetos.
  • Normalmente, un objeto “tiene” un grupo de otros objetos y sirve como contenedor o colección.
  • El componente puede existir sin el contenedor y puede vincularse a varios contenedores al mismo tiempo.
class Author:
    def __init__(self, name, surname):
        self.name = name
        self.surname = surname

    def __repr__(self):
        return f"{self.name} {self.surname}"


class Book:
    def __init__(self, title, author: Author):
        self.title = title
        self.author = author

    def __repr__(self):
        return f"Titulo: {self.title} - author: {self.author}"


author = Author("pedro", "lopez")
book = Book("Titulo", author)
print(book)

Author puede existir sin Book.

Composición

  • La composición es un tipo específico de agregación en la que un objeto se compone de una o más instancias del otro.
  • La diferencia es que el componente sólo puede existir como parte del contenedor.
class Book:
    def __init__(self, title):
        self.title = title
        self.chapters = []

    def add_chapter(self, chapter):
        self.chapters.append(chapter)

    def total_pages(self):
        total = 0
        for chapter in self.chapters:
            total += chapter.pages
        return total


chapter_1 = Chapter("Chapter 1", 50)
chapter_2 = Chapter("Chapter 2", 25)

book = Book("Titulo")
book.add_chapter(chapter_1)
book.add_chapter(chapter_2)

print(book.total_pages())

Chapter no tiene sentido si no es dentro de Book.

Herencia

  • La herencia es la capacidad de crear nuevas clases sobre otras existentes.
  • Principal ventaja: reutilización de código.
  • Consecuencia: las subclases tienen la misma interfaz que su clase padre (no se puede ocultar un método de la superclase).

Polimorfismo

  • El polimorfismo es la capacidad que tiene un programa de detectar la verdadera clase de un objeto e invocar su implementación, incluso aunque su tipo real sea desconocido en el contexto actual.

Referencia