Generic Geometric Shapes with Trait Bounds
Rust's powerful generics and trait system allow you to write flexible and reusable code. This challenge focuses on leveraging trait bounds to define a common interface for different geometric shapes, enabling generic functions to operate on them uniformly.
Problem Description
You are tasked with creating a system that can calculate the area and perimeter of various geometric shapes. To achieve this, you need to define a common trait that all shapes will implement. This trait should specify methods for calculating both the area and perimeter. Subsequently, you will create a generic function that can accept any type implementing this trait and perform these calculations.
What needs to be achieved:
- Define a
Shapetrait with methodsarea()andperimeter(). - Implement this
Shapetrait for at least two distinct geometric shapes (e.g.,Circle,Rectangle). - Create a generic function
print_shape_infothat takes any typeTas an argument, whereTmust implement theShapetrait. This function should call thearea()andperimeter()methods and print the results in a user-friendly format.
Key requirements:
- The
Shapetrait should have two methods:area(): Returns af64representing the area.perimeter(): Returns af64representing the perimeter.
- The
print_shape_infofunction should be generic over a typeTthat satisfies theShapetrait bound. - The output of
print_shape_infoshould clearly indicate the shape type (if possible through introspection or by passing a name) and its calculated area and perimeter.
Expected behavior:
When print_shape_info is called with an instance of Circle, it should correctly calculate and print its area and perimeter. The same should happen for Rectangle and any other shapes you choose to implement.
Important edge cases to consider:
- The values of dimensions (e.g., radius, width, height) can be floating-point numbers.
- Consider the mathematical formulas for area and perimeter for each shape.
Examples
Example 1: Circle
Input:
let circle = Circle { radius: 5.0 };
print_shape_info(&circle);
Output:
Shape Info:
Type: Circle
Area: 78.53981633974483
Perimeter: 31.41592653589793
Explanation: The area of a circle is π * r^2, and the perimeter is 2 * π * r.
Example 2: Rectangle
Input:
let rectangle = Rectangle { width: 4.0, height: 6.0 };
print_shape_info(&rectangle);
Output:
Shape Info:
Type: Rectangle
Area: 24.0
Perimeter: 20.0
Explanation: The area of a rectangle is width * height, and the perimeter is 2 * (width + height).
Constraints
- All calculations involving area and perimeter should use
f64for precision. - The input dimensions for shapes can be any non-negative
f64values. - The generic function
print_shape_infoshould not make assumptions about the specific concrete type, only that it implements theShapetrait.
Notes
- You'll need to import
std::f64::consts::PIfor circle calculations. - To display the "Type" in the output, you might need to add a method to the
Shapetrait or pass a string name toprint_shape_info. Consider how to best achieve this. - Think about how to define the
Shapetrait and implement it for your chosen shapes. - The core of the challenge is correctly defining the generic function with the
Shapetrait bound.