Hone logo
Hone
Problems

Embracing Shapes: A Go Polymorphism Challenge

This challenge will guide you through implementing polymorphism in Go using interfaces. You'll create a system that can handle different geometric shapes, allowing you to perform common operations like calculating their area and perimeter in a uniform way, regardless of the specific shape. This is a fundamental concept for building flexible and extensible software.

Problem Description

Your task is to design and implement a Go program that demonstrates polymorphism. You need to create a system that can represent different geometric shapes (e.g., Circle, Rectangle) and perform common operations on them, such as calculating their area and perimeter. The key requirement is to use Go's interface mechanism to achieve polymorphism, meaning you should be able to treat different shape types uniformly through a common interface.

Key Requirements:

  1. Define a Shape Interface: This interface should declare methods for Area() and Perimeter(), both returning a float64.
  2. Implement Concrete Shape Types: Create at least two concrete types that represent geometric shapes. For this challenge, implement:
    • Circle: With a Radius field.
    • Rectangle: With Width and Height fields.
  3. Implement Interface Methods: Each concrete shape type must implement the Shape interface by providing implementations for Area() and Perimeter() methods.
    • Circle Area: π * radius²
    • Circle Perimeter: 2 * π * radius
    • Rectangle Area: width * height
    • Rectangle Perimeter: 2 * (width + height)
  4. Demonstrate Polymorphism: Create a function that accepts a slice of Shape interface types. This function should iterate through the shapes and print the type of shape, its calculated area, and its perimeter.

Expected Behavior:

The program should correctly calculate and print the area and perimeter for each shape instance, demonstrating that the Area() and Perimeter() methods are called on the appropriate underlying concrete type, even when accessed through the Shape interface.

Edge Cases:

  • Consider how your calculations would behave with zero or negative dimensions. For this challenge, assume valid positive dimensions for simplicity.

Examples

Example 1:

Input:
Shapes:
- Circle with radius 5.0
- Rectangle with width 4.0 and height 6.0

Output:
Shape: Circle, Area: 78.53981633974483, Perimeter: 31.41592653589793
Shape: Rectangle, Area: 24.0, Perimeter: 20.0

Explanation: The program iterates through the provided shapes. For the Circle, it calculates Area (π * 5.0²) and Perimeter (2 * π * 5.0). For the Rectangle, it calculates Area (4.0 * 6.0) and Perimeter (2 * (4.0 + 6.0)).

Example 2:

Input:
Shapes:
- Circle with radius 1.0
- Rectangle with width 1.0 and height 1.0

Output:
Shape: Circle, Area: 3.141592653589793, Perimeter: 6.283185307179586
Shape: Rectangle, Area: 1.0, Perimeter: 4.0

Explanation: Similar to Example 1, but with smaller dimensions. This demonstrates correctness for unit values.

Constraints

  • All dimensions (radius, width, height) will be positive float64 values.
  • The number of shapes in the collection will be between 1 and 100.
  • The program should not rely on external libraries for mathematical constants like π; use math.Pi from the standard library.

Notes

  • Think about how an interface in Go defines a "contract." Any type that implements all the methods defined in the interface is considered to satisfy that interface.
  • You'll likely need to import the math package for the value of π.
  • When printing the shape type, you can use reflection (fmt.Printf("%T", shape)) or explicitly store the type name as a string within your concrete types. For this challenge, explicitly storing the type name is a good approach.
Loading editor...
go