Skip to content

Commit babb0c4

Browse files
committed
feat: mouredev#28-Python
Reto mouredev#28-Python realizado por mrodara
1 parent 2973f80 commit babb0c4

File tree

1 file changed

+190
-0
lines changed

1 file changed

+190
-0
lines changed
Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
### Principio SOLID de Sustitución de Liskov (Liskov Substitution Principle, LSP)
2+
3+
'''
4+
LSP establece que: Un objeto de una subclase debe ser sustituible por un objeto de su clase base
5+
sin alterar el correcto funcionamiento del programa.
6+
7+
LSP se centra en garantizar que las subclases no modifiquen el comportamiento esperado de la clase base.
8+
En otras palabras, cualquier clase hija debe ser capaz de reemplazar a su clase padre sin introducir errores o
9+
comportamientos inesperados.
10+
'''
11+
'''
12+
Ventajas:
13+
- Mejora la reutilización de código.
14+
- Aporta coherencia en la jerarquía de clases.
15+
- Ayuda a evitar la dependencia de la implementación.
16+
'''
17+
18+
# Ejemplo que viola LSP
19+
# Clase Base
20+
class CuentaBancaria():
21+
def __init__(self, saldo):
22+
self.saldo = saldo
23+
24+
def retirar(self, monto):
25+
if monto <= self.saldo:
26+
self.saldo -= monto
27+
else:
28+
raise ValueError("Saldo insuficiente para retirar de la cuenta")
29+
30+
# Clase Derivada
31+
class CuentaAhorros(CuentaBancaria):
32+
33+
def retirar(self, monto):
34+
raise NotImplementedError("No se puede realizar retirada de la cuenta ahorro")
35+
36+
# Al aplicar polimorfismo en este caso está violando el principio de Sustitución de Liskov
37+
'''
38+
CuentaAhorros no puede ser sustituida por CuentaBancaria sin alterar
39+
40+
def procesar_retiro(cuenta, monto):
41+
cuenta.retirar(monto)
42+
43+
cuenta = CuentaBancaria(1000)
44+
procesar_retiro(cuenta, 100) # Funciona correctamente
45+
46+
cuenta_ahorros = CuentaAhorros(1000)
47+
procesar_retiro(cuenta_ahorros, 100) # Lanza NotImplementedError
48+
'''
49+
50+
# Arreglemos el ejemplo empleando abstracciones para restricciones específicas
51+
from abc import ABC, abstractmethod
52+
53+
class CuentaBancaria(ABC):
54+
55+
def __init__(self, saldo):
56+
self.saldo = saldo
57+
58+
@abstractmethod
59+
def retirar(self, monto):
60+
pass
61+
62+
class CuentaCorriente(CuentaBancaria):
63+
def retirar(self, monto):
64+
if monto <= self.saldo:
65+
self.saldo -= monto
66+
print("Retirada de efectivo realizada correctamente")
67+
else:
68+
raise ValueError("Su saldo es inferior a la cantidad a retirar, abortando operación")
69+
70+
class CuentaAhorros(CuentaBancaria):
71+
def retirar(self, monto):
72+
if monto > self.saldo:
73+
raise ValueError("Saldo insuficiente, abortando operación")
74+
75+
if monto >= 500:
76+
raise ValueError("La retirada máxima para este tipo de cuenta es de 500€") # Restricción específica para esta clase
77+
78+
self.saldo -= monto
79+
80+
# Prueba de funcionamiento correcto
81+
def procesar_retirada(cuenta, monto):
82+
try:
83+
cuenta.retirar(monto)
84+
print(f"Proceso finalizado, su saldo actual tras la operación es de {cuenta.saldo} €")
85+
except ValueError as e:
86+
print(e)
87+
88+
c1 = CuentaCorriente(1000)
89+
c2 = CuentaAhorros(2000)
90+
91+
procesar_retirada(c1, 500) # Funciona correctamente
92+
procesar_retirada(c2, 200) # Funciona correctamente
93+
procesar_retirada(c2, 700) # Lanza ValueError
94+
95+
### EJERCICIO EXTRA
96+
97+
from abc import ABC, abstractmethod
98+
99+
class Vehicle(ABC):
100+
def __init__(self, type, max_speed, speed=0):
101+
self.type = type
102+
self.max_speed = max_speed
103+
self.speed = speed if speed <= max_speed else max_speed
104+
105+
@abstractmethod
106+
def speed_up(self, qty):
107+
pass
108+
109+
@abstractmethod
110+
def speed_down(self, qty):
111+
pass
112+
113+
114+
class Car(Vehicle):
115+
def speed_up(self, qty):
116+
if self.speed + qty <= self.max_speed:
117+
self.speed += qty
118+
print(f"Acelerar terminado, velocidad actual: {self.speed}")
119+
else:
120+
raise ValueError("La cantidad a acelerar supera la velocidad máxima del vehículo")
121+
122+
def speed_down(self, qty):
123+
if self.speed - qty >= 0:
124+
self.speed -= qty
125+
print(f"Frenar terminado, velocidad actual: {self.speed}")
126+
else:
127+
self.speed = 0
128+
print("Vehículo parado")
129+
130+
131+
class Truck(Vehicle):
132+
def speed_up(self, qty):
133+
if self.speed + qty <= self.max_speed:
134+
self.speed += qty
135+
print(f"Acelerar terminado, velocidad actual: {self.speed}")
136+
else:
137+
raise ValueError("La cantidad a acelerar supera la velocidad máxima del camión")
138+
139+
def speed_down(self, qty):
140+
if self.speed - qty >= 0:
141+
self.speed -= qty
142+
print(f"Frenar terminado, velocidad actual: {self.speed}")
143+
else:
144+
self.speed = 0
145+
print("Vehículo parado")
146+
147+
148+
class ElectricCar(Vehicle):
149+
def speed_up(self, qty):
150+
if self.speed + qty <= self.max_speed:
151+
self.speed += qty
152+
print(f"Acelerar terminado, velocidad actual: {self.speed}")
153+
else:
154+
raise ValueError("La cantidad a acelerar supera la velocidad máxima del vehículo eléctrico")
155+
156+
def speed_down(self, qty):
157+
if self.speed - qty >= 0:
158+
self.speed -= qty
159+
print(f"Frenar terminado, velocidad actual: {self.speed}")
160+
else:
161+
self.speed = 0
162+
print("Vehículo parado")
163+
164+
165+
# Realización de pruebas
166+
def test_speed(vehicle):
167+
print(f"Inicio de las pruebas con {vehicle.type}")
168+
try:
169+
vehicle.speed_up(25)
170+
vehicle.speed_down(5)
171+
vehicle.speed_up(vehicle.max_speed + 1)
172+
vehicle.speed_down(vehicle.speed)
173+
except ValueError as e:
174+
print(e)
175+
print("-" * 60)
176+
177+
cars = [
178+
Car("Ferrari F50", 300, 125),
179+
Truck("Mercedes-Benz Actros", 150, 80),
180+
ElectricCar("Tesla Model S", 120, 125)
181+
]
182+
183+
for car in cars:
184+
test_speed(car) # Realizar pruebas con cada tipo de vehículo
185+
186+
187+
### FIN EJERCICIO EXTRA
188+
189+
190+
### FIN Principio SOLID de Sustitución de Liskov (Liskov Substitution Principle, LSP)

0 commit comments

Comments
 (0)