Menu
Coddy logo textTech

Implementación implícita

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

En muchos lenguajes orientados a objetos como Java o C#, debes declarar explícitamente que un tipo implementa una interfaz usando palabras clave como implements. Go adopta un enfoque diferente: la implementación de interfaces es implícita.

Un tipo satisface una interfaz simplemente implementando todos sus métodos. No es necesario declarar la relación en ningún lugar. El compilador lo determina automáticamente.

type Writer interface {
    Write(data string) int
}

type FileWriter struct {
    Filename string
}

// FileWriter implementa implícitamente Writer
func (f FileWriter) Write(data string) int {
    fmt.Println("Writing to", f.Filename)
    return len(data)
}

Observa que no hay ninguna declaración implements Writer en FileWriter. Como FileWriter tiene un método Write(data string) int que coincide con la firma de la interfaz, satisface automáticamente la interfaz Writer.

Este diseño tiene una consecuencia poderosa: puedes definir interfaces después de que los tipos ya existan. Si una biblioteca de terceros tiene un tipo con métodos que necesitas, puedes crear una interfaz que ya cumpla sin modificar el código original.

func Save(w Writer, content string) {
    w.Write(content)
}

func main() {
    fw := FileWriter{Filename: "data.txt"}
    Save(fw, "Hello!")  // Funciona porque FileWriter satisface Writer
}

La implementación implícita mantiene el código de Go desacoplado y flexible. Los tipos no necesitan conocer las interfaces de antemano, lo que facilita componer sistemas a partir de partes independientes.

challenge icon

Desafío

Fácil

Construyamos un sistema de entrega de mensajes que demuestre cómo los tipos satisfacen implícitamente las interfaces en Go. Crearás diferentes tipos de mensajeros que satisfacen todos la misma interfaz, sin declarar nunca esa relación explícitamente.

Organizarás tu código en dos archivos:

  • messengers.go: Define una interfaz Messenger con un solo método Send(message string) string. Después, crea dos estructuras que satisfarán implícitamente esta interfaz:
    • EmailMessenger con un campo Address (cadena)
    • SMSMessenger con un campo PhoneNumber (cadena)
    Cada estructura debe tener un método Send que devuelva una cadena que describa la entrega. Ninguna estructura debe declarar explícitamente que implementa Messenger: Go lo determinará automáticamente basándose en las firmas de los métodos.
  • main.go: Crea una función llamada DeliverMessage que acepte cualquier Messenger y una cadena de mensaje, y después devuelva el resultado de llamar a Send. Lee la información de contacto de la entrada, crea ambos tipos de mensajeros y usa tu función para entregar mensajes a través de cada uno.

Se proporcionarán las siguientes entradas:

  • Línea 1: Dirección de correo electrónico
  • Línea 2: Número de teléfono
  • Línea 3: Mensaje que se enviará

Tus métodos Send deben devolver cadenas con estos formatos:

  • EmailMessenger: Email to [Address]: [message]
  • SMSMessenger: SMS to [PhoneNumber]: [message]

Por ejemplo, dadas alice@example.com, 555-1234 y Hello!, tu salida debería ser:

Email to alice@example.com: Hello!
SMS to 555-1234: Hello!

La idea clave aquí es que tu función DeliverMessage acepta cualquier Messenger, y tanto EmailMessenger como SMSMessenger satisfacen esa interfaz simplemente por tener un método Send coincidente. No hay ninguna palabra clave implements: la implementación implícita de Go se encarga de todo.

Pruébalo tú mismo

package main

import (
	"bufio"
	"fmt"
	"os"
)

// TODO: Crea una función DeliverMessage que acepte cualquier Messenger
// y una cadena de mensaje, luego devuelve el resultado de llamar a Send

func main() {
	reader := bufio.NewReader(os.Stdin)
	
	// Read email address
	email, _ := reader.ReadString('\n')
	email = email[:len(email)-1]
	
	// Lee el número de teléfono
	phone, _ := reader.ReadString('\n')
	phone = phone[:len(phone)-1]
	
	// Lee el mensaje
	message, _ := reader.ReadString('\n')
	if len(message) > 0 && message[len(message)-1] == '\n' {
		message = message[:len(message)-1]
	}
	
	// TODO: Crea un EmailMessenger con la dirección de correo electrónico
	
	// TODO: Crea un SMSMessenger con el número de teléfono
	
	// TODO: Usa DeliverMessage para enviar el mensaje a través de cada messenger
	// e imprime los resultados
}
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