Menu
Coddy logo textTech

Polimorfismo mediante interfaces

Parte de la sección Programación Orientada a Objetos del Journey de GO de Coddy. Lección 41 de 107.

El polimorfismo permite tratar distintos tipos de manera uniforme mediante una interfaz compartida. En Go, esto se logra completamente mediante interfaces, sin herencia ni jerarquías de clases.

Cuando una función acepta un tipo de interfaz como parámetro, se puede pasar cualquier tipo concreto que implemente esa interfaz. La función no necesita conocer el tipo específico. Solo le importa el comportamiento definido por la interfaz:

type Speaker interface {
    Speak() string
}

type Dog struct{ Name string }
func (d Dog) Speak() string { return "Woof!" }

type Cat struct{ Name string }
func (c Cat) Speak() string { return "Meow!" }

func MakeSound(s Speaker) {
    fmt.Println(s.Speak())
}

Ahora MakeSound funciona con cualquier tipo que tenga un método Speak():

func main() {
    dog := Dog{Name: "Rex"}
    cat := Cat{Name: "Whiskers"}
    
    MakeSound(dog)  // ¡Guau!
    MakeSound(cat)  // ¡Miau!
}

La misma llamada a una función produce un comportamiento diferente según el tipo real que se le pase. Esto es el polimorfismo en acción. La función MakeSound se escribe una sola vez, pero funciona con un número ilimitado de tipos, siempre que satisfagan la interfaz Speaker.

Este enfoque mantiene tu código flexible y extensible. Añadir un nuevo tipo que hable no requiere cambios en las funciones existentes; solo tienes que implementar la interfaz y funcionará automáticamente.

challenge icon

Desafío

Fácil

Construyamos un sistema de descripción de vehículos que demuestre el polimorfismo en acción. Crearás diferentes tipos de vehículos que compartirán un comportamiento común mediante una interfaz y, después, escribirás una única función que funcione con cualquier vehículo.

Organizarás tu código en dos archivos:

  • vehicles.go: Define una interfaz Describer que requiera un método Describe() string. Después, crea tres tipos de vehículos que implementen esta interfaz a su manera:
    • Car con los campos Brand y Model. Su método Describe() devuelve Car: [Brand] [Model]
    • Motorcycle con los campos Brand y EngineCC (int). Su método Describe() devuelve Motorcycle: [Brand] [EngineCC]cc
    • Bicycle con el campo Type (como "Mountain" o "Road"). Su método Describe() devuelve Bicycle: [Type]
  • main.go: Crea una función llamada PrintDescription que acepte cualquier Describer e imprima el resultado de llamar a Describe(). Lee los detalles de los vehículos desde la entrada, crea uno de cada tipo de vehículo y pasa cada uno a PrintDescription para demostrar que la misma función funciona con los tres tipos diferentes.

Se proporcionarán las siguientes entradas:

  • Línea 1: marca del Car
  • Línea 2: modelo del Car
  • Línea 3: marca del Motorcycle
  • Línea 4: cilindrada del motor del Motorcycle (entero)
  • Línea 5: tipo de Bicycle

Por ejemplo, dadas las entradas Toyota, Camry, Honda, 600 y Mountain, tu salida debería ser:

Car: Toyota Camry
Motorcycle: Honda 600cc
Bicycle: Mountain

Observa que PrintDescription no necesita saber si está recibiendo un Car, Motorcycle o Bicycle. Simplemente llama a Describe() y cada tipo responde con su propia salida única. Esto es polimorfismo: una función y múltiples comportamientos.

Pruébalo tú mismo

package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
	"strings"
)

// TODO: Crea una función llamada PrintDescription que acepte cualquier Describer
// e imprima el resultado de llamar a Describe()

func main() {
	reader := bufio.NewReader(os.Stdin)

	// Lee los detalles del coche
	carBrand, _ := reader.ReadString('\n')
	carBrand = strings.TrimSpace(carBrand)
	carModel, _ := reader.ReadString('\n')
	carModel = strings.TrimSpace(carModel)

	// Lee los detalles de la motocicleta
	motoBrand, _ := reader.ReadString('\n')
	motoBrand = strings.TrimSpace(motoBrand)
	motoEngineStr, _ := reader.ReadString('\n')
	motoEngineStr = strings.TrimSpace(motoEngineStr)
	motoEngine, _ := strconv.Atoi(motoEngineStr)

	// Lee los detalles de la bicicleta
	bicycleType, _ := reader.ReadString('\n')
	bicycleType = strings.TrimSpace(bicycleType)

	// TODO: Crea un Car, Motorcycle y Bicycle usando los valores de entrada

	// TODO: Llama a PrintDescription para cada vehículo para demostrar el polimorfismo
	fmt.Println("TODO: Print vehicle descriptions")
}
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Programación Orientada a Objetos

Practica por tu cuenta: Compilador de Go online