#Ejercicio:
Cree una superclase llamada Shape(), que es la base de las clases Reactangle() y Square(), defina los métodos compute_area y compute_perimeter en Shape() y luego, utilizando polimorfismo, redefina los métodos adecuadamente en Rectangle y en Square.
Utilizando las clases Point() y Line() defina una nueva superclase Shape() con la siguiente estructura:
Utilice herencia, composición, encapsulación y polimorfismo para definir las clases. Todos los atributos deben tener sus respectivos setters y getters.
import math
class Point:
definition: str = "Entidad geometrica abstracta que representa una ubicación en un espacio."
def __init__(self, x: float = 0, y: float = 0):
self._x = x
self._y = y
def move(self, new_x: float, new_y: float):
self._x = new_x
self._y = new_y
def reset(self):
self._x = 0
self._y = 0
def compute_distance(self, point: "Point") -> float:
return ((self._x - point._x) ** 2 + (self._y - point._y) ** 2) ** 0.5
def set_x(self, x: float): self._x = x
def get_x(self) -> float: return self._x
def set_y(self, y: float): self._y = y
def get_y(self) -> float: return self._y
class Line:
def __init__(self, start: Point, end: Point):
self._start = start
self._end = end
def length(self) -> float:
return self._start.compute_distance(self._end)
def move(self, dx: float, dy: float):
self._start.move(self._start.get_x() + dx, self._start.get_y() + dy)
self._end.move(self._end.get_x() + dx, self._end.get_y() + dy)
def __str__(self):
return f"({self._start.get_x()}, {self._start.get_y()}) → ({self._end.get_x()}, {self._end.get_y()})"
class Shape:
def __init__(self, vertices=None):
self._vertices = list(vertices) if vertices else []
self._edges = self._compute_edges()
self._is_regular = False
self._inner_angles = []
def _compute_edges(self):
edges = []
n = len(self._vertices)
for i in range(n):
edges.append(Line(self._vertices[i], self._vertices[(i + 1) % n]))
return edges
def compute_perimeter(self) -> float:
total = 0.0
for e in self._edges:
total += e.length()
return total
def compute_area(self) -> float:
raise NotImplementedError
def compute_inner_angles(self):
raise NotImplementedError
def get_vertices(self): return self._vertices
def get_edges(self): return self._edges
def get_inner_angles(self): return self._inner_angles
def get_is_regular(self): return self._is_regular
def set_vertices(self, vertices):
self._vertices = list(vertices)
self._edges = self._compute_edges()
def set_is_regular(self, value: bool): self._is_regular = value
def set_inner_angles(self, angles): self._inner_angles = list(angles)
class Rectangle(Shape):
def __init__(self, p1: Point, p2: Point):
v = [
Point(min(p1.get_x(), p2.get_x()), min(p1.get_y(), p2.get_y())),
Point(max(p1.get_x(), p2.get_x()), min(p1.get_y(), p2.get_y())),
Point(max(p1.get_x(), p2.get_x()), max(p1.get_y(), p2.get_y())),
Point(min(p1.get_x(), p2.get_x()), max(p1.get_y(), p2.get_y())),
]
super().__init__(v)
self._width = self._vertices[1].get_x() - self._vertices[0].get_x()
self._height = self._vertices[3].get_y() - self._vertices[0].get_y()
self._is_regular = (self._width == self._height)
def compute_area(self) -> float:
return self._width * self._height
def compute_interference_point(self, p: Point) -> bool:
return (self._vertices[0].get_x() <= p.get_x() <= self._vertices[2].get_x() and
self._vertices[0].get_y() <= p.get_y() <= self._vertices[2].get_y())
def compute_inner_angles(self):
self._inner_angles = [90, 90, 90, 90]
return self._inner_angles
class Square(Rectangle):
def __init__(self, p1: Point, p2: Point):
super().__init__(p1, p2)
if self._width != self._height:
raise ValueError("Los lados no son iguales: no es un cuadrado.")
self._is_regular = True
class Triangle(Shape):
def __init__(self, p1: Point, p2: Point, p3: Point):
super().__init__([p1, p2, p3])
def compute_area(self) -> float:
a = self._edges[0].length()
b = self._edges[1].length()
c = self._edges[2].length()
if not (a + b > c and a + c > b and b + c > a):
raise ValueError("Los puntos no forman un triángulo válido.")
s = (a + b + c) / 2
area = (s * (s - a) * (s - b) * (s - c)) ** 0.5
self._is_regular = (a == b == c)
return area
def compute_inner_angles(self):
a = self._edges[0].length()
b = self._edges[1].length()
c = self._edges[2].length()
A = math.degrees(math.acos((b*b + c*c - a*a) / (2*b*c)))
B = math.degrees(math.acos((a*a + c*c - b*b) / (2*a*c)))
C = 180 - A - B
self._inner_angles = [A, B, C]
return self._inner_angles
class Isosceles(Triangle):
def __init__(self, p1: Point, p2: Point, p3: Point):
super().__init__(p1, p2, p3)
a = self._edges[0].length()
b = self._edges[1].length()
c = self._edges[2].length()
if not ((a == b and b != c) or (a == c and a != b) or (b == c and b != a)):
raise ValueError("No corresponde a un triángulo isósceles.")
class Equilateral(Triangle):
def __init__(self, p1: Point, p2: Point, p3: Point):
super().__init__(p1, p2, p3)
a = self._edges[0].length()
b = self._edges[1].length()
c = self._edges[2].length()
if not (a == b == c):
raise ValueError("No corresponde a un triángulo equilátero.")
self._is_regular = True
class Scalene(Triangle):
def __init__(self, p1: Point, p2: Point, p3: Point):
super().__init__(p1, p2, p3)
a = self._edges[0].length()
b = self._edges[1].length()
c = self._edges[2].length()
if a == b or a == c or b == c:
raise ValueError("No corresponde a un triángulo escaleno.")
class TriRectangle(Triangle):
def __init__(self, p1: Point, p2: Point, p3: Point):
super().__init__(p1, p2, p3)
a = self._edges[0].length()
b = self._edges[1].length()
c = self._edges[2].length()
right = (
math.isclose(a*a + b*b, c*c, rel_tol=1e-9) or
math.isclose(a*a + c*c, b*b, rel_tol=1e-9) or
math.isclose(b*b + c*c, a*a, rel_tol=1e-9)
)
if not right:
raise ValueError("No corresponde a un triángulo rectángulo.")
if __name__ == "__main__":
r = Rectangle(Point(0, 0), Point(4, 3))
s = Square(Point(1, 1), Point(5, 5))
t = Triangle(Point(0, 0), Point(4, 0), Point(0, 3))
print("Rectángulo área:", r.compute_area())
print("Cuadrado perímetro:", s.compute_perimeter())
print("Triángulo ángulos:", [round(x, 2) for x in t.compute_inner_angles()])Incluya el ejercicio de clase en el repositorio. El restaurante reinterpretado Agregue establecedores y captadores a todas las subclases para el elemento del menú Anular calculate_total_price() según la composición del pedido (por ejemplo, si el pedido incluye un plato principal, aplicar algún descuento en bebidas) Agregue la clase Pago() siguiendo el ejemplo de la clase.
class MenuItem:
def __init__(self, name: str, price: float, content: str, category: str):
self._name = name
self._price = float(price)
self._content = content
self._category = category
def set_name(self, name): self._name = name
def get_name(self): return self._name
def set_price(self, price): self._price = float(price)
def get_price(self): return self._price
def set_content(self, content): self._content = content
def get_content(self): return self._content
def set_category(self, category): self._category = category
def get_category(self): return self._category
class CaesarSalad(MenuItem):
def __init__(self, salad_type: str):
super().__init__("Caesar Salad", 15000,
"Lettuce, croutons, Parmesan cheese, Caesar dressing",
"starter")
self._salad_type = salad_type
def set_salad_type(self, salad_type): self._salad_type = salad_type
def get_salad_type(self): return self._salad_type
class Nachos(MenuItem):
def __init__(self, topping: str):
super().__init__("Nachos with a topping", 18000,
"Corn chips, chosen topping, melted cheese, pico de gallo",
"starter")
self._topping = topping
def set_topping(self, topping): self._topping = topping
def get_topping(self): return self._topping
class Wrap(MenuItem):
def __init__(self, wrap_type: str):
super().__init__("Veggie Wrap", 14000,
"Tortilla with fresh vegetables or steak",
"starter")
self._wrap_type = wrap_type
def set_wrap_type(self, wrap_type): self._wrap_type = wrap_type
def get_wrap_type(self): return self._wrap_type
class BologneseSpaghetti(MenuItem):
def __init__(self, pasta_type: str):
super().__init__("Spaghetti Bolognese", 28000,
"Spaghetti, beef tomato sauce, onion, garlic, grated cheese",
"main")
self._pasta_type = pasta_type
def set_pasta_type(self, pasta_type): self._pasta_type = pasta_type
def get_pasta_type(self): return self._pasta_type
class BeefSteak(MenuItem):
def __init__(self, doneness: str):
super().__init__("Beef Steak", 35000,
"Grilled beef steak with mashed potatoes and vegetables",
"main")
self._doneness = doneness
def set_doneness(self, doneness): self._doneness = doneness
def get_doneness(self): return self._doneness
class Salmon(MenuItem):
def __init__(self, cooking_style: str):
super().__init__("Salmon with Rice", 38000,
"Salmon (style by client), rice, steamed vegetables, lemon",
"main")
self._cooking_style = cooking_style
def set_cooking_style(self, cooking_style): self._cooking_style = cooking_style
def get_cooking_style(self): return self._cooking_style
class FruitJuice(MenuItem):
def __init__(self, fruit_flavor: str):
super().__init__("Fruit Juice", 8000,
"Fresh juice blended with water and a touch of sugar",
"drink")
self._fruit_flavor = fruit_flavor
def set_fruit_flavor(self, fruit_flavor): self._fruit_flavor = fruit_flavor
def get_fruit_flavor(self): return self._fruit_flavor
class Lemonade(MenuItem):
def __init__(self, flavor: str):
super().__init__("Lemonade", 9000,
"Lemon, mint, water, sugar",
"drink")
self._flavor = flavor
def set_flavor(self, flavor): self._flavor = flavor
def get_flavor(self): return self._flavor
class Cake(MenuItem):
def __init__(self, main_ingredient: str):
super().__init__("Cake", 12000,
"Cake base with chosen ingredient, cinnamon, nutmeg, frosting",
"dessert")
self._main_ingredient = main_ingredient
def set_main_ingredient(self, main_ingredient): self._main_ingredient = main_ingredient
def get_main_ingredient(self): return self._main_ingredient
class Tart(MenuItem):
def __init__(self, flavor: str):
super().__init__("Tart", 14000,
"Shortcrust base, chosen flavor, optional meringue or sugar",
"dessert")
self._flavor = flavor
def set_flavor(self, flavor): self._flavor = flavor
def get_flavor(self): return self._flavor
class Order:
def __init__(self):
self._orderlist = []
def add_item_order(self, item: MenuItem):
self._orderlist.append(item)
print(f"{item.get_name()} added to order. Price: {item.get_price()} COP")
def get_orderlist(self):
return self._orderlist
def total_price(self):
total = sum(item.get_price() for item in self._orderlist)
has_main = any(item.get_category() == "main" for item in self._orderlist)
if has_main:
for item in self._orderlist:
if item.get_category() == "drink":
total -= item.get_price() * 0.10
return total
class MedioPago:
def pagar(self, monto):
raise NotImplementedError("Subclases deben implementar pagar()")
class Tarjeta(MedioPago):
def __init__(self, numero, cvv):
self._numero = numero
self._cvv = cvv
def pagar(self, monto):
print("Pago realizado con tarjeta.")
class Efectivo(MedioPago):
def __init__(self, monto_entregado):
self._monto_entregado = monto_entregado
def pagar(self, monto):
if self._monto_entregado >= monto:
print(f"Pago realizado en efectivo. Cambio: {self._monto_entregado - monto} COP")
else:
print(f"Fondos insuficientes. Faltan {monto - self._monto_entregado} COP")
```