coding challenge

Reto de programación 4: Área de un polígono

Este reto de programación consiste en crear un método imprima por pantalla el área de un polígono. El enunciado reza lo siguiente:

/*
 * Crea una única función (importante que sólo sea una) que sea capaz
 * de calcular y retornar el área de un polígono.
 * - La función recibirá por parámetro sólo UN polígono a la vez.
 * - Los polígonos soportados serán Triángulo, Cuadrado y Rectángulo.
 * - Imprime el cálculo del área de un polígono de cada tipo.
 */

Importante detenernos en la petición expresa que se hace en el primer párrafo: «crear una única función (importante que sólo sea una)«. Es decir, esa función recibirá «algo» y ese algo puede ser «cualquier cosa». Cualquier cosa que sea un polígono, claro.

Los polígonos soportados serán triángulo, cuadrado y rectángulo. La fórmula para calcular el área de cada uno de ellos es diferente, sin embargo nuestra función debe ser capaz de calcularla independientemente de cúal de ellos sea.

Las fórmulas son:

  • Triángulo: base por altura dividido entre 2
  • Cuadrado: lado al cuadrado (o lado por lado)
  • Rectángulo: ancho por alto

Pensando en este reto como algo que podría escalar en el futuro y que nos podrían pedir añadir nuevos polígonos, y cada uno de ellos tiene su fórmula y los datos de entrada que necesitaremos serán diferentes, vamos a utilizar la programación orientada a objetos.

Tendremos una clase por cada polígono, que implementará una interfaz que contiene un método para calcular el área. De este modo, toda clase que implemente esta interfaz deberá tener su propio método para calcular su área.

Así, la lógica del cálculo del área de cada polígono, es responsabilidad de cada clase, y podremos añadir en un futuro tantas clases como queramos sin modificar el código ni la lógica de nuestra función principal.

El ejercicio lo he resuelto así:

<?php

declare(strict_types=1);

function printArea(Polygon $polygon): float
{
    return $polygon->calcArea();
}

interface Polygon
{
    public function calcArea();
}

class Triangle implements Polygon
{
    private $base;
    private $height;

    public function __construct(float $base, float $height)
    {
        $this->base = $base;
        $this->height = $height;
    }

    public function calcArea(): float
    {
        return ($this->base * $this->height) / 2;
    }
}

class Square implements Polygon
{
    private $side;

    public function __construct(float $side)
    {
        $this->side = $side;
    }

    public function calcArea(): float
    {
        return $this->side * $this->side;
    }
}

class Rectangle implements Polygon
{
    private $width;
    private $height;

    public function __construct(float $width, float $height)
    {
        $this->width = $width;
        $this->height = $height;
    }

    public function calcArea(): float
    {
        return $this->width * $this->height;
    }
}

echo "El área del triángulo es " . printArea(new Triangle(2.2, 4)) . "\n";
echo "El área del cuadrado es " . printArea(new Square(3)) . "\n";
echo "El área del rectángulo es " . printArea(new Rectangle(5, 6)) . "\n";

La función única que nos piden en printArea(). Esta función recibe como parámetro un objeto de tipo Polygon, que son cualquiera de las clases que hemos creado y que implementan la interfaz Polygon.

Dentro de esta función, simplemente retornamos el valor que nos devuelve el método calcArea() que tiene nuestro objeto $polygon, y que para cada clase (Triangle, Square o Rectangle) implementa una lógica del cálculo del área diferente.

Disclaimer

Por simplificar, he puesto todo el código junto. Lo ideal es que hicieras uso de namespaces y que cada clase y la interfaz estuvieran en ficheros php separados.

También me gustaría comentar que si utilizas PHP 8, podrías hacer uso de constructor properties promotion para simplificar el código de nuestras clases.

Puedes verlo también en GitHub.

¿Te ha resultado útil esta información? 🍺

Si este post te ha resuelto un problema, invítame a un café o a una cerveza. Con este pequeño gesto me animas a seguir escribiendo.

Comentarios

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *:

  • El fin del tratamiento es únicamente la moderación de comentarios para evitar spam
  • La legitimación es tu consentimiento al comentar
  • No se comunicará ningún dato a terceros salvo por obligación legal
  • Tienes derecho al acceso, rectificación y eliminación de los comentarios