Recapitulação - Calculadora de Formas
Parte da seção Object Oriented Programming do Journey de Python da Coddy — lição 27 de 64.
Desafio
MédioNeste desafio, você implementará um sistema de calculadora de formas que demonstra polimorfismo.
Implemente as classes necessárias nos seguintes arquivos (procure pelos comentários TODO em cada arquivo):
shape.py- Defina a classe base abstrataShapecircle.py- Implemente a classeCirclerectangle.py- Implemente a classeRectangletriangle.py- Implemente a classeTriangleunknownshape.py- Crie uma classe não derivada demonstrando duck typingshapecalculator.py- Implemente a funcionalidade da calculadora
Siga os comentários TODO em cada arquivo para orientação passo a passo. A suíte de testes abrangente ajudará você a entender o comportamento esperado e garantirá que sua implementação atenda a todos os requisitos corretamente.
Folha de consulta
Como não há conteúdo de lição fornecido, apenas instruções de desafio, não posso criar uma folha de dicas. As folhas de dicas devem ser baseadas principalmente na teoria e nos conceitos da lição, com o conteúdo do desafio apenas complementando quando contiver explicações úteis adicionais não cobertas na lição.
Experimente você mesmo
from circle import Circle
from rectangle import Rectangle
from triangle import Triangle
from unknownshape import UnknownShape
from shapecalculator import ShapeCalculator
import math
# Manipulador de casos de teste
test_case = input()
def test_basic_functionality():
calculator = ShapeCalculator()
# Teste com Círculo
circle = Circle(5)
print(f"Testing {circle}")
results = calculator.process_shape(circle)
print(f"Results: {results}")
print()
# Teste com Retângulo
rectangle = Rectangle(4, 6)
print(f"Testing {rectangle}")
results = calculator.process_shape(rectangle)
print(f"Results: {results}")
print()
# Teste com Triângulo
triangle = Triangle(3, 4, 5)
print(f"Testing {triangle}")
results = calculator.process_shape(triangle)
print(f"Results: {results}")
print()
# Teste com UnknownShape (duck typing)
unknown = UnknownShape("Custom", 10)
print(f"Testing {unknown}")
results = calculator.process_shape(unknown)
print(f"Results: {results}")
def test_edge_cases():
calculator = ShapeCalculator()
# Teste com valores zero
print("Testing zero values:")
circle = Circle(0)
print(f"Circle(0) area: {circle.area()}, perimeter: {circle.perimeter()}")
rectangle = Rectangle(0, 5)
print(f"Rectangle(0, 5) area: {rectangle.area()}, perimeter: {rectangle.perimeter()}")
# Teste com valores muito grandes
print("\
Testing large values:")
large_circle = Circle(1000000)
print(f"Circle(1000000) area: {large_circle.area():.2e}, perimeter: {large_circle.perimeter():.2e}")
# Teste com valores decimais
print("\
Testing decimal values:")
decimal_circle = Circle(0.5)
print(f"Circle(0.5) area: {decimal_circle.area()}, perimeter: {decimal_circle.perimeter()}")
decimal_triangle = Triangle(2.5, 3.5, 4.5)
print(f"Triangle(2.5, 3.5, 4.5) area: {decimal_triangle.area()}, perimeter: {decimal_triangle.perimeter()}")
def test_inheritance():
# Cria instâncias de cada forma
circle = Circle(5)
rectangle = Rectangle(4, 6)
triangle = Triangle(3, 4, 5)
unknown = UnknownShape("Custom", 10)
# Testa relações de herança
from shape import Shape
print(f"Circle is a Shape: {isinstance(circle, Shape)}")
print(f"Rectangle is a Shape: {isinstance(rectangle, Shape)}")
print(f"Triangle is a Shape: {isinstance(triangle, Shape)}")
print(f"UnknownShape is a Shape: {isinstance(unknown, Shape)}")
# Testa disponibilidade de métodos
print("\
Method availability:")
for shape_name, shape_obj in [("Circle", circle), ("Rectangle", rectangle),
("Triangle", triangle), ("UnknownShape", unknown)]:
print(f"{shape_name} has area(): {hasattr(shape_obj, 'area')}")
print(f"{shape_name} has perimeter(): {hasattr(shape_obj, 'perimeter')}")
print(f"{shape_name} has describe(): {hasattr(shape_obj, 'describe')}")
def test_polymorphism():
calculator = ShapeCalculator()
# Cria uma lista de diferentes formas
shapes = [
Circle(5),
Rectangle(4, 6),
Triangle(3, 4, 5),
UnknownShape("Custom", 10)
]
print("Testing polymorphic behavior:")
for i, shape in enumerate(shapes, 1):
print(f"\
Shape {i}: {shape.__class__.__name__}")
results = calculator.process_shape(shape)
print(f"Results: {results}")
def test_duck_typing():
calculator = ShapeCalculator()
# Cria uma classe completamente nova que possui os métodos necessários
class CustomDuckShape:
def __init__(self, name, factor):
self.name = name
self.factor = factor
def area(self):
return self.factor * 3
def perimeter(self):
return self.factor * 12
def describe(self):
return f"This is a {self.name} duck-typed shape with area {self.area()} and perimeter {self.perimeter()}"
def __str__(self):
return f"Custom {self.name} with factor {self.factor}"
# Teste com a forma customizada via duck-typing
duck_shape = CustomDuckShape("DuckTyped", 5)
print(f"Testing duck typing with: {duck_shape}")
results = calculator.process_shape(duck_shape)
print(f"Results: {results}")
# Compara com uma forma regular
circle = Circle(5)
print(f"\
Comparing with regular shape: {circle}")
results = calculator.process_shape(circle)
print(f"Results: {results}")
def test_invalid_inputs():
calculator = ShapeCalculator()
try:
# Teste com raio negativo
print("Testing Circle with negative radius:")
negative_circle = Circle(-5)
results = calculator.process_shape(negative_circle)
print(f"Results: {results}")
except Exception as e:
print(f"Error with negative circle: {e}")
try:
# Teste com triângulo inválido (lados que não podem formar um triângulo)
print("\
Testing invalid Triangle (1, 1, 10):")
invalid_triangle = Triangle(1, 1, 10) # Viola a desigualdade triangular
results = calculator.process_shape(invalid_triangle)
print(f"Results: {results}")
# Verifica se o cálculo da área retorna um resultado válido
area = invalid_triangle.area()
if math.isnan(area) or not isinstance(area, float) or area <= 0:
print(f"Invalid triangle area: {area}")
except Exception as e:
print(f"Error with invalid triangle: {e}")
# Executa o teste apropriado com base na entrada
if test_case == "basic_functionality":
test_basic_functionality()
elif test_case == "edge_cases":
test_edge_cases()
elif test_case == "inheritance":
test_inheritance()
elif test_case == "polymorphism":
test_polymorphism()
elif test_case == "duck_typing":
test_duck_typing()
elif test_case == "invalid_inputs":
test_invalid_inputs()
else:
# Caso de teste padrão
test_basic_functionality()Todas as lições de Object Oriented Programming
1Fundamentos de POO
Arquivos ExternosIntrodução à POOClasses vs ObjetosO Parâmetro selfMétodosAtributosMétodo Construtor (__init__)Recapitulação - Calculadora Simples4Herança
Herança BásicaA Função super()Sobrescrita de MétodoHerança MúltiplaOrdem de Resolução de MétodosRecapitulação - Hierarquia de Funcionários7Métodos Especiais
Introdução aos Métodos MágicosSobrecarga de OperadoresMétodos Mágicos de ContêinerRecapitulação - Lista Personalizada10Padrões de Projeto Parte 1
Introdução a Padrões de ProjetoPadrão SingletonPadrão FactoryPadrão ObserverPadrão Strategy2Decoradores
Introdução aos DecoradoresDecorador de PropriedadeDecorador de Método EstáticoDecorador de Método de Classe5Polimorfismo
Sobrescrita de Método RevisitadaDuck TypingClasses e Métodos AbstratosDesign de InterfacesRecapitulação - Calculadora de Formas8Conceitos Avançados de POO
Composição vs HerançaMixinsMétodos Estáticos e de ClasseDecoradores de ClasseGerenciadores de Contexto11Padrões de Projeto Parte 2
Padrão CommandPadrão AdapterPadrão DecoratorPadrão Template MethodPadrão StatePadrão Composite3Propriedades de Classe
Variáveis de Instância vs de ClasseDecoradores de PropriedadeAtributos PrivadosRecapitulação - Gerenciador de Conta Bancária6Encapsulamento
Membros Públicos, Protegidos e PrivadosModificadores de AcessoOcultação de InformaçãoProperty Decorators AvançadosRecapitulação - Sistema de Registro de Alunos12Projeto: Gerenciamento de Biblioteca
Visão Geral do ProjetoClasses Livro e Usuário