Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Grupo - 2 - Informe-Prinicipios Del Paradigma Oo
Grupo - 2 - Informe-Prinicipios Del Paradigma Oo
1
Contenido
1. Introducción ...............................................................................................................................3
1.1 Definición de Programación Orientada a Objetos (OOP) ...................................................3
1.2 Programación Orientada a Objetos (OOP) en Python .........................................................3
1.3 Antecedentes y Breve historia y evolución del paradigma OOP.........................................4
1.4 Importancia en el desarrollo de software moderno .............................................................4
1.5 Ventajas y desventajas de la POO ......................................................................................5
2. Fundamentos de la Programación Orientada a Objetos ..............................................................6
2.1 Clases y Objetos .................................................................................................................6
2.2 Clases y Objetos en Python ................................................................................................7
2.3 Principios de diseño de clases.............................................................................................9
2.4 Encapsulamiento .............................................................................................................. 10
2.5 Herencia ........................................................................................................................... 12
2.6 La abstracción .................................................................................................................. 14
2.7 Polimorfismo .................................................................................................................... 16
3. Principios SOLID en la Programación Orientada a Objetos ..................................................... 17
4. Relaciones entre Objetos .......................................................................................................... 19
4.1 Asociación ........................................................................................................................ 19
4.2 Agregación ....................................................................................................................... 20
4.3 Composición .................................................................................................................... 22
2
1. Introducción
La Programación Orientada a Objetos (OOP) se erige como un paradigma esencial en la ingeniería
de software al proporcionar una metodología estructural que organiza el código de manera eficiente.
Este enfoque se fundamenta en el concepto de "objetos", entidades virtuales que encapsulan tanto
datos como comportamientos relacionados entre sí.
En la Programación Orientada a Objetos, cada objeto es una instancia única de una clase, que actúa
como un plano o prototipo para definir las propiedades y acciones que los objetos pueden llevar a
cabo. Este enfoque facilita la conceptualización y modelado de sistemas complejos, al emular de
manera más fiel la realidad y las relaciones entre distintas entidades.
En Python, las clases actúan como plantillas para la creación de objetos, definiendo sus atributos
(datos) y métodos (funciones). Los objetos interactúan entre sí mediante el intercambio de mensajes,
lo que permite una programación más modular y flexible.
La OOP en Python ofrece una serie de ventajas, como la reutilización de código, la modularidad, la
facilidad para mantener y actualizar el código, y la capacidad para modelar de manera eficiente
sistemas complejos. Esto la convierte en una opción popular para el desarrollo de una amplia gama
de aplicaciones, desde aplicaciones web hasta sistemas de inteligencia artificial.
3
1.3 Antecedentes y Breve historia y evolución del paradigma OOP
La Programación Orientada a Objetos (POO) surge a finales de la década de 1960 como una respuesta
a las limitaciones de la programación tradicional, como la dificultad para mantener y reutilizar código.
Fue en la década de 1980 con la popularización de lenguajes como C++ y Java que OOP alcanzó su
prominencia. Desde entonces, ha evolucionado constantemente con contribuciones significativas de
la comunidad de desarrollo.
4
1.5 Ventajas y desventajas de la POO
Ventajas:
1. Facilidad de mantenimiento:
La POO facilita la organización del código en módulos independientes, lo que hace que sea
más fácil de entender y mantener.
Los cambios en una clase o un objeto solo afectan a esa clase o objeto, lo que reduce el riesgo
de errores y facilita la corrección de errores.
Las clases y objetos pueden ser reutilizados en diferentes proyectos, lo que ahorra tiempo y
esfuerzo.
Las bibliotecas de clases predefinidas proporcionan una amplia gama de funcionalidades que
pueden ser utilizadas directamente en los proyectos.
3. Extensibilidad:
La POO facilita la creación de nuevas clases que heredan de las clases existentes, lo que
permite ampliar la funcionalidad de las clases existentes.
4. Modularidad:
La POO facilita la organización del código en módulos independientes, lo que hace que sea
más fácil de probar y depurar.
Los módulos independientes pueden ser desarrollados y probados por separado, lo que reduce
el tiempo de desarrollo y mejora la calidad del código.
Desventajas:
1. Complejidad:
La POO puede ser más compleja de aprender y entender que la programación tradicional.
El uso de clases, objetos, herencia y polimorfismo puede ser un desafío para los principiantes.
2. Eficiencia:
5
La POO puede ser menos eficiente que la programación tradicional en algunos casos.
El uso de clases, objetos y herencia puede generar un código más grande y lento.
3. Curva de aprendizaje:
La POO tiene una curva de aprendizaje más pronunciada que la programación tradicional.
Se requiere tiempo y esfuerzo para dominar los conceptos de la POO y poder utilizarlos de
forma eficaz.
Esto puede ser un obstáculo para los principiantes o para aquellos que no tienen mucho
tiempo para dedicarse a la programación.
Objeto: Un objeto, por otro lado, es una instancia particular de una clase. Es una
entidad concreta que posee características específicas y puede realizar acciones de
acuerdo con lo definido por la clase a la que pertenece. Volviendo al ejemplo, un
objeto específico podría ser un "Automóvil Toyota Rojo". Aquí, el objeto hereda las
propiedades y métodos definidos en la clase "Automóvil" y las adapta a sus
características únicas, como el modelo específico y el color.
6
b. Propiedades y Métodos:
Propiedades: Las propiedades son atributos que describen las características del
objeto. En el contexto del automóvil, las propiedades pueden incluir detalles como
el modelo, el color, el año de fabricación, el número de puertas, etc. Estas
propiedades encapsulan la información esencial que define al objeto.
Métodos: Los métodos son funciones o acciones que un objeto puede llevar a cabo.
En el caso del automóvil, los métodos pueden ser funciones como arrancar, detener,
acelerar, frenar, etc. Estos métodos definen el comportamiento del objeto y cómo
interactúa con su entorno. Pueden modificar las propiedades del objeto o realizar
acciones específicas asociadas con ese objeto en particular.
Objetos:
Un objeto es una instancia de una clase. Se crea mediante la invocación del constructor de la clase,
que se llama __init__() en Python. Los objetos tienen acceso a los atributos y métodos definidos en
su clase.
La Programación Orientada a Objetos en Python permite la creación de clases y objetos para modelar
entidades del mundo real de manera efectiva, lo que facilita la creación de sistemas más complejos y
modulares.
class Persona:
# Constructor
def _init_(self):
self.ci = None
self.nombre = None
self.ap_pat = None
7
self.ap_mat = None
# Metodos set
def set_ci(self, ci):
self.ci = ci
# Metodos get
def get_ci(self):
return self.ci
def get_nombre(self):
return self.nombre
def get_ap_pat(self):
return self.ap_pat
def get_ap_mat(self):
return self.ap_mat
# Otros Metodos
def saludar(self):
print(f"Hola, soy {self.nombre} y tengo {self.edad} años.")
8
def nombre_completo(self):
if self.nombre == None:
return "Introducir los datos de la persona"
else:
nombre_com = (
f"Carnet de identidad: {str(self.ci)}\n "
f"Nombre: {str(self.nombre)}\n"
f"Ap. Paterno: {str(self.ap_pat)}\n"
f"Ap. Materno: {str(self.ap_mat)}"
)
return nombre_com
people = Persona()
people.set_ci(123456)
people.set_nombre("Josue")
people.set_ap_pat("Coro")
people.set_ap_mat("Orellana")
print(
f"Carnet de identidad: {people.get_ci()} \n Nombre: {people.get_nombre()} \n ap_paterno:
{people.get_ap_pat()} \n ap_materno: {people.get_ap_mat()}")
En este ejemplo, Persona es una clase que tiene varios atributos (nombre, CI, Apellido paterno,
Apellido materno) y un método (saludar()).
La reutilización es un principio fundamental del diseño de clases que busca crear clases que puedan
ser utilizadas en diferentes proyectos. Para lograr esto, las clases deben ser:
9
Modulares: Deben estar bien organizadas en módulos independientes.
Extensibles: Deben ser fáciles de modificar y ampliar.
Documentadas: Deben tener una documentación clara y completa
Técnicas para la reutilización:
Herencia: Permite crear nuevas clases que heredan las características y el
comportamiento de clases existentes.
Interfaces: Definen contratos que deben ser implementados por las clases.
Composición: Permite crear objetos complejos a partir de objetos más simples.
Patrones de diseño: Proporcionan soluciones reutilizables a problemas comunes de
diseño de software.
Cohesión (ampliado)
La cohesión es un principio fundamental del diseño de clases que se refiere a la fuerza con la que los
elementos (atributos y métodos) de una clase están relacionados entre sí. Una clase con alta cohesión
tiene un único propósito bien definido y todos sus elementos trabajan juntos para lograr ese propósito.
Niveles de cohesión:
Alta cohesión: Todos los elementos de la clase están estrechamente relacionados y
trabajan juntos para lograr un único objetivo.
Cohesión media: Algunos elementos de la clase no están directamente relacionados con
el propósito principal de la clase, pero aún pueden ser útiles.
Baja cohesión: Los elementos de la clase no están relacionados entre sí y la clase tiene
múltiples responsabilidades.
Mayor facilidad de comprensión: Las clases con alta cohesión son más fáciles de entender
y mantener.
Menor probabilidad de errores: Las clases con alta cohesión son menos propensas a tener
errores debido a la menor interacción entre diferentes funcionalidades.
Mayor reusabilidad: Las clases con alta cohesión son más fáciles de reutilizar en
diferentes contextos.
2.4 Encapsulamiento
1. Concepto y Beneficios:
10
Encapsulamiento: Es el principio de ocultar los detalles internos de un objeto y
exponer solo lo necesario para su interacción. Se logra mediante la definición de
propiedades y métodos como públicos, privados o protegidos. La encapsulación es
un principio fundamental de la POO que consiste en ocultar los detalles de
implementación de un objeto a los demás objetos.
2. Encapsulamiento en Python
En Python, se utiliza una convención de nomenclatura para indicar la visibilidad de los atributos y
métodos de una clase:
Los atributos y métodos que comienzan con un guion bajo ( _ ) se consideran como miembros
protegidos y no deben ser accedidos directamente desde fuera de la clase.
Los atributos y métodos que comienzan con dos guiones bajos ( __ ) se consideran como miembros
privados y no deben ser accedidos directamente desde fuera de la clase. Sin embargo, Python cambia
el nombre de estos miembros en tiempo de ejecución agregando el nombre de la clase al principio, lo
que dificulta el acceso desde fuera de la clase.
class Persona:
def __init__(self, nombre, edad):
self._nombre = nombre # atributo protegido
self.__edad = edad # atributo privado
def saludar(self):
print(f"Hola, soy {self._nombre} y tengo {self.__edad} años.")
11
persona1 = Persona("Juan", 30)
3. Características:
Acceso controlado: Los objetos solo pueden acceder a los datos y métodos de otros
objetos a través de interfaces públicas.
2.5 Herencia
La herencia es un concepto clave en la Programación Orientada a Objetos (POO) que permite a
una clase, denominada subclase o clase hija, heredar las propiedades y comportamientos de otra
clase, conocida como superclase o clase padre. Este mecanismo proporciona una forma de
reutilizar y extender el código, promoviendo la creación de jerarquías de clases más ricas y
especializadas.
En Python, la herencia se establece al definir una clase y especificar su superclase entre paréntesis
en la definición de la clase. La subclase hereda todos los atributos y métodos de la superclase y
puede agregar nuevos atributos y métodos, o incluso sobrescribir los métodos existentes para
modificar su comportamiento.
class Estudiante(per.Persona):
def __init__(self):
# Llamar un metodo de la clase padre al constructor de la clase que herede
super().__init__()
self.codigo_estudiante = None
self.correo_institucional = None
self.seguro = None
12
self.codigo_estudiante = codigo
def get_codigo_estudiante(self):
return self.codigo_estudiante
def get_correo_institucional(self):
return self.correo_institucional
def get_seguro(self):
return self.seguro
import Estudiante
estudiante = Estudiante.Estudiante()
# es metodo de la clase persona que hereda a la clase estudiante
estudiante.set_ci(13540503)
estudiante.set_nombre("Josue")
estudiante.set_ap_pat("Coro")
estudiante.set_ap_mat("Orellana")
#los metodos de la clase estudiante
estudiante.set_codigo_estudiante(104245)
estudiante.set_correo_institucional("[email protected]")
estudiante.set_seguro(True)
# Cuadro de mensaje
13
y edad, y también podría tener sus propias propiedades específicas de un estudiante,
como el número de estudiante y la especialidad.
Herencia Múltiple: En contraste, la herencia múltiple permite que una clase herede
de más de una clase padre. En el ejemplo, una clase "Estudiante" podría heredar tanto
de la clase "Persona" como de la clase "Curso". Esto implica que la clase "Estudiante"
tendría acceso tanto a las propiedades generales de una persona como a las
específicas de un curso. La herencia múltiple puede ser poderosa, pero también puede
introducir complejidades en el diseño y la resolución de conflictos si varias clases
padre tienen métodos o propiedades con el mismo nombre.
2. Ventajas de la herencia
2.6 La abstracción
La abstracción es un concepto fundamental en la Programación Orientada a Objetos que se refiere a
la capacidad de representar las características esenciales de un objeto, mientras se ocultan los detalles
complejos o irrelevantes de su implementación interna. En otras palabras, la abstracción permite
enfocarse en los aspectos relevantes de un objeto y sus interacciones, sin necesidad de conocer todos
los detalles de cómo se implementa.
Abstracción en Python
La abstracción en Python se refiere a la capacidad de crear clases y objetos que representan entidades
del mundo real de manera simplificada, centrándose en sus aspectos esenciales y ocultando los
detalles complejos de su implementación interna. En la Programación Orientada a Objetos (OOP) en
14
Python, la abstracción se logra mediante la definición de clases que encapsulan datos (atributos) y
comportamientos (métodos) relevantes para el objeto, sin exponer la complejidad de cómo se
implementan esos datos y comportamientos.
Por ejemplo, supongamos que queremos representar un vehículo en Python. Podemos crear una clase
llamada Vehiculo que tenga atributos como marca, modelo y color, y métodos como acelerar y frenar.
Estos métodos encapsularían la lógica para mover el vehículo hacia adelante o detenerlo, pero los
detalles internos de cómo se logra esto (por ejemplo, mediante un motor de combustión interna o un
motor eléctrico) se ocultan dentro de la clase Vehiculo.
class Vehiculo:
def __init__(self, marca, modelo, color):
self.marca = marca
self.modelo = modelo
self.color = color
def acelerar(self):
print(f"{self.marca} {self.modelo} acelerando...")
def frenar(self):
print(f"{self.marca} {self.modelo} frenando...")
15
2.7 Polimorfismo
Definición y tipos de polimorfismo
En Python, el polimorfismo se logra mediante el uso de métodos con el mismo nombre en diferentes
clases. Cuando se llama a un método en un objeto, Python determina qué versión del método utilizar
según el tipo de objeto en tiempo de ejecución.
class Animal:
def hacer_sonido(self):
pass # Método abstracto
class Perro(Animal):
def hacer_sonido(self):
return "Guau!"
class Gato(Animal):
def hacer_sonido(self):
return "Miau!"
16
print(hacer_sonido_animal(mi_gato)) # Output: Miau!
Tipos de polimorfismo:
El Principio de Responsabilidad Única destaca la importancia de que una clase tenga una única razón
para cambiar, es decir, una única responsabilidad en el sistema. Esto se traduce en clases que se
centran exclusivamente en una tarea específica. Al seguir el SRP, se mejora la modularidad del código
y se facilita su mantenimiento. Una clase que se ocupa de la manipulación de archivos, por ejemplo,
17
debería estar enfocada solo en esa tarea y no asumir responsabilidades adicionales, como la
manipulación de datos.
El Principio Abierto/Cerrado aboga por la extensibilidad del código sin modificar su código fuente
original. Para lograr esto, las clases y módulos se diseñan de manera que puedan extenderse para
agregar nuevas funcionalidades sin alterar el código existente. Esto promueve la adaptabilidad del
sistema a cambios y mejoras, reduciendo el riesgo de introducir errores en código previamente
funcional. La extensibilidad se logra mediante la creación de clases abiertas para la extensión, pero
cerradas para la modificación.
El Principio de Segregación de Interfaces aborda el diseño de interfaces para evitar que las clases se
vean obligadas a implementar métodos que no utilizan. En lugar de interfaces monolíticas, se favorece
la creación de interfaces más pequeñas y específicas para cada contexto. Esto evita que las clases
implementen funcionalidades innecesarias, promoviendo una mayor cohesión y evitando la violación
del SRP. Las interfaces deben ser client-specific y no contener métodos que el cliente no necesite.
18
4. Relaciones entre Objetos
4.1 Asociación
La asociación es una relación entre dos o más objetos donde cada uno puede existir de manera
independiente del otro. Esta relación puede ser temporal o permanente y es bidireccional. En la
asociación, los objetos interactúan entre sí, pero no están directamente vinculados en términos de
pertenencia. Pueden referirse entre sí para cumplir con ciertos objetivos, pero no comparten una
dependencia fuerte. Las asociaciones pueden ser de varios tipos, como uno a uno, uno a muchos o
muchos a muchos.
La asociación en Python es una relación entre dos o más objetos donde cada objeto puede existir de
manera independiente del otro, pero interactúan entre sí para lograr un objetivo común. En la
asociación, los objetos se relacionan de forma bidireccional, y pueden tener una relación temporal o
permanente. Esta relación se establece mediante el uso de referencias entre los objetos.
class Estudiante:
def __init__(self, nombre):
self.nombre = nombre
def estudiar(self):
return f"{self.nombre} está estudiando."
class Curso:
def __init__(self, nombre):
self.nombre = nombre
19
print(curso1.agregar_estudiante(estudiante1)) # Output: Se ha agregado a Juan al curso de
Matemáticas.
print(estudiante1.estudiar()) # Output: Juan está estudiando.
Ejemplo de Asociación:
En un sistema de gestión escolar, la relación entre las clases Estudiante y Curso puede
considerarse una asociación. Un estudiante puede estar asociado con varios cursos y, a
su vez, un curso puede tener múltiples estudiantes asociados.
Muchos a muchos: Un Estudiante puede tomar varios Cursos, y un Curso puede tener
varios Estudiantes.
4.2 Agregación
La agregación es una relación más fuerte que la asociación. En una relación de agregación, un objeto
puede estar compuesto por varios sub objetos, pero esos sub objetos pueden existir de manera
independiente. La relación de agregación se representa a menudo mediante un diamante negro en los
diagramas UML. La destrucción del objeto principal no implica necesariamente la destrucción de los
objetos agregados.
La agregación en Python es una relación entre dos objetos donde un objeto contiene una referencia a
otro objeto, pero ambos pueden existir de forma independiente. En la agregación, un objeto puede
estar compuesto por varios subobjetos, pero esos subobjetos pueden existir fuera del objeto principal.
La agregación se utiliza para modelar relaciones del tipo "todo-parte", donde el objeto principal es el
"todo" y los objetos secundarios son las "partes".
class Rueda:
def __init__(self, modelo):
self.modelo = modelo
class Automovil:
def __init__(self, marca):
self.marca = marca
self.ruedas = [] # Lista para almacenar las ruedas del automóvil
20
def agregar_rueda(self, rueda):
self.ruedas.append(rueda)
En este ejemplo, la clase Automovil representa el objeto principal que contiene una lista de objetos
Rueda. La relación de agregación se establece cuando se agregan las ruedas al automóvil mediante el
método agregar_rueda(). Aunque las ruedas están asociadas con el automóvil, pueden existir de forma
independiente. La agregación se utiliza comúnmente para modelar relaciones de composición, como
en este caso, donde un automóvil está compuesto por varias ruedas.
Ejemplo de Agregación:
En el contexto de una biblioteca, la relación entre una clase Biblioteca y Libros puede ser
una agregación. La biblioteca puede contener varios libros, y estos libros pueden existir
fuera de la biblioteca.
21
4.3 Composición
La composición es la relación más fuerte entre objetos. En una relación de composición, un objeto
está formado por la combinación de varios subobjetos, y la existencia del objeto principal implica la
existencia de los subobjetos. La composición se representa a menudo mediante un diamante negro
lleno en los diagramas UML. La destrucción del objeto principal implica la destrucción de los objetos
compuestos.
La composición en Python es una relación entre dos objetos donde un objeto está formado por la
combinación de varios subobjetos y la existencia del objeto principal implica la existencia de los
subobjetos.
class Motor:
def __init__(self, tipo):
self.tipo = tipo
class Automovil:
def __init__(self, marca, modelo):
self.marca = marca
self.modelo = modelo
self.motor = Motor("Gasolina") # Objeto de la clase Motor como parte del automóvil
def descripcion(self):
return f"Automóvil {self.marca} {self.modelo} con motor {self.motor.tipo}"
22
automóvil y no puede existir independientemente de él. La composición se utiliza para modelar
relaciones más fuertes entre objetos, donde los subobjetos forman parte integral del objeto principal.
Ejemplo de Composición:
23