Menu
CoddyTech

Ringkasan: Kalkulator Bentuk

Termasuk bagian Pemrograman Berorientasi Objek dalam perjalanan Python di Coddy. Pelajaran 27 dari 64.

challenge icon

Tantangan

Sedang

Dalam tantangan ini, kamu akan menerapkan sistem kalkulator bentuk yang menunjukkan polimorfisme.

Terapkan class yang diperlukan dalam file berikut (cari komentar TODO di setiap file):

  • shape.py - Definisikan class dasar abstrak Shape
  • circle.py - Terapkan class Circle
  • rectangle.py - Terapkan class Rectangle
  • triangle.py - Terapkan class Triangle
  • unknownshape.py - Buat class yang tidak diturunkan dari class lain untuk menunjukkan duck typing
  • shapecalculator.py - Terapkan fungsionalitas kalkulator

Ikuti komentar TODO di setiap file sebagai panduan langkah demi langkah. Rangkaian kasus uji yang lengkap akan membantumu memahami perilaku yang diharapkan dan memastikan implementasimu menangani semua persyaratan dengan benar.

Coba sendiri

from circle import Circle
from rectangle import Rectangle
from triangle import Triangle
from unknownshape import UnknownShape
from shapecalculator import ShapeCalculator
import math

# Penangan kasus uji
test_case = input()

def test_basic_functionality():
    calculator = ShapeCalculator()
    
    # Uji dengan Circle
    circle = Circle(5)
    print(f"Testing {circle}")
    results = calculator.process_shape(circle)
    print(f"Results: {results}")
    print()
    
    # Uji dengan Rectangle
    rectangle = Rectangle(4, 6)
    print(f"Testing {rectangle}")
    results = calculator.process_shape(rectangle)
    print(f"Results: {results}")
    print()
    
    # Uji dengan Triangle
    triangle = Triangle(3, 4, 5)
    print(f"Testing {triangle}")
    results = calculator.process_shape(triangle)
    print(f"Results: {results}")
    print()
    
    # Uji dengan 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()
    
    # Uji dengan nilai nol
    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()}")
    
    # Uji dengan nilai yang sangat besar
    print("\
Testing large values:")
    large_circle = Circle(1000000)
    print(f"Circle(1000000) area: {large_circle.area():.2e}, perimeter: {large_circle.perimeter():.2e}")
    
    # Uji dengan nilai desimal
    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():
    # Buat instance dari setiap bentuk
    circle = Circle(5)
    rectangle = Rectangle(4, 6)
    triangle = Triangle(3, 4, 5)
    unknown = UnknownShape("Custom", 10)
    
    # Uji hubungan pewarisan
    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)}")
    
    # Uji ketersediaan method
    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()
    
    # Buat list berisi berbagai bentuk
    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()
    
    # Buat class baru yang memiliki method yang diperlukan
    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}"
    
    # Uji dengan bentuk kustom yang menggunakan 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}")
    
    # Bandingkan dengan bentuk biasa
    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:
        # Uji dengan jari-jari negatif
        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:
        # Uji dengan segitiga tidak valid (sisi-sisinya tidak dapat membentuk segitiga)
        print("\
Testing invalid Triangle (1, 1, 10):")
        invalid_triangle = Triangle(1, 1, 10)  # Melanggar ketaksamaan segitiga
        results = calculator.process_shape(invalid_triangle)
        print(f"Results: {results}")
        # Periksa apakah perhitungan luas menghasilkan nilai yang valid
        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}")

# Jalankan pengujian yang sesuai berdasarkan input
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:
    # Kasus uji bawaan
    test_basic_functionality()

Semua pelajaran di Pemrograman Berorientasi Objek

Latihan sendiri: Compiler Python online