Hone logo
Hone
Problems

Designing a Shape Hierarchy with Abstract Classes in TypeScript

This challenge focuses on leveraging TypeScript's abstract classes to model a hierarchy of geometric shapes. Abstract classes allow you to define common properties and methods for a group of related classes without requiring subclasses to implement all of them immediately, promoting code reusability and a clear inheritance structure. You'll be creating an abstract Shape class and then deriving concrete shape classes from it.

Problem Description

You are tasked with creating a TypeScript program that defines an abstract Shape class and two concrete classes, Circle and Rectangle, that inherit from it. The Shape class should be abstract and define an abstract method getArea() that returns the area of the shape. It should also have a protected color property. The Circle and Rectangle classes must implement the getArea() method and initialize the color property.

Key Requirements:

  • Abstract Shape Class: Define an abstract class named Shape with a protected color property (string) and an abstract getArea() method (returning a number).
  • Concrete Circle Class: Create a class named Circle that extends Shape. It should have a radius property (number) and implement the getArea() method, calculating the area of the circle (π * radius²). It should also take the radius and color as arguments in its constructor.
  • Concrete Rectangle Class: Create a class named Rectangle that extends Shape. It should have width and height properties (both numbers) and implement the getArea() method, calculating the area of the rectangle (width * height). It should also take the width, height, and color as arguments in its constructor.
  • Error Handling: Ensure that the getArea() methods return 0 if any input is invalid (e.g., negative radius, width, or height).

Expected Behavior:

The program should successfully define the abstract class and concrete classes, allowing you to create instances of Circle and Rectangle and calculate their areas. The color property should be accessible and modifiable within the derived classes.

Edge Cases to Consider:

  • Negative radius, width, or height values.
  • Zero radius, width, or height values (should still calculate area correctly).

Examples

Example 1:

Input:
const circle = new Circle(5, "red");
const rectangle = new Rectangle(4, 6, "blue");

Output:
circle.getArea() // 78.53981633974483
rectangle.getArea() // 24
circle.color // "red"
rectangle.color // "blue"

Explanation: A circle with radius 5 and a rectangle with width 4 and height 6 are created. Their areas are calculated and the colors are accessed.

Example 2:

Input:
const invalidCircle = new Circle(-2, "green");
const invalidRectangle = new Rectangle(-1, 3, "yellow");

Output:
invalidCircle.getArea() // 0
invalidRectangle.getArea() // 0

Explanation: Invalid circles and rectangles (with negative dimensions) are created. Their getArea() methods return 0 due to the error handling.

Example 3:

Input:
const zeroCircle = new Circle(0, "purple");
const zeroRectangle = new Rectangle(0, 0, "orange");

Output:
zeroCircle.getArea() // 0
zeroRectangle.getArea() // 0

Explanation: Circles and rectangles with zero dimensions are created. Their getArea() methods return 0.

Constraints

  • The getArea() method must return a number.
  • The color property must be a string.
  • The radius, width, and height must be numbers.
  • The code must be valid TypeScript.
  • The Shape class must be abstract.
  • The getArea() method in Shape must be abstract.

Notes

  • Remember to use the abstract keyword to define the abstract class and abstract method.
  • Use the protected keyword for the color property to allow access within derived classes.
  • Consider using Math.PI for the value of pi when calculating the circle's area.
  • Think about how to handle invalid input values gracefully. Returning 0 is a simple approach, but you could also throw an error if desired.
Loading editor...
typescript