Lecciones del módulo (1/5)
Interfaces: definir un comportamiento
Una interfaz en Go es un conjunto de firmas de métodos. un valor
implementa la interfaz si tiene todos esos métodos - no
implements, sin extends, sin registro explícito. es el
modelo a menudo llamado "tipificación estructural" o "tipificación estática de pato":
el compilador verifica la conformidad en el momento de la compilación, pero en función de
forma, no en declaraciones.
Declarando una interfaz
type Greeter interface {
Greet() string
}Convención: nombres que terminan en -er para interfaces de método único
(CÓDIGOF1, CÓDIGOF2, CÓDIGOF3, CÓDIGOF4). Pequeñas interfaces
(1 o 2 métodos) son idiomáticos: la biblioteca estándar está llena de
pequeñas interfaces que se componen juntas (io.ReadWriter,
CÓDIGOPH6,…).
Implementación implícita
type Person struct{ Name string }
func (p Person) Greet() string {
return "ciao " + p.Name
}
// Person satisfies Greeter because it has the required method.
var s Greeter = Person{Name: "Ada"}
fmt.Println(s.Greet())Sin palabra clave. Si el tipo tiene los métodos, se puede asignar a una variable de ese tipo de interfaz. Eso es todo.
Polimorfismo a través de la interfaz
type Robot struct{ ID string }
func (r Robot) Greet() string { return "bip " + r.ID }
func greet(s Greeter) {
fmt.Println(s.Greet())
}
greet(Person{Name: "Ada"})
greet(Robot{ID: "R2"})greet acepta cualquier tipo que satisfaga Greeter. Este es el camino hacia adelante
de hacer polimorfismo: sin jerarquías, solo capacidad.
La interfaz vacía
var x interface{} = 42
var y any = "ciao" // any is the built-in alias of interface{}interface{} (o any desde Go 1.18) no requiere métodos, por lo que cualquier
el valor lo satisface. Útil para contenedores genéricos, pero para extraer.
el valor concreto que necesita es una afirmación de tipo o un cambio de tipo
(próximas lecciones).
Conjunto de métodos: valor frente a receptor de puntero (vista previa)
Recuerde del Módulo 5:
- Los métodos con un receptor de valor están en el conjunto de métodos de
Ty*T. - Los métodos con un receptor de puntero SÓLO están en el conjunto de métodos de
*T.
Consecuencia práctica:
type Counter struct{ N int }
func (c *Counter) Inc() { c.N++ }
type Incrementer interface { Inc() }
var i Incrementer = &Counter{} // OK: *Counter has Inc()
// var j Incrementer = Counter{} // ERROR: Counter (value) does NOTCuando un método tiene un receptor de puntero, debe asignar un puntero a la variable de interfaz.
Pruébalo
Defina una interfaz Greeter con una cadena Greet() de un solo método.
Mostrar pista
Sintaxis: `type Name interface { Method(args) return }`.
Solución disponible después de 3 intentos
Implementar Greeter en un nuevo tipo de Robot con cadena de ID de campo; el método devuelve 'bip ' + ID.
Mostrar pista
Sin `implements`: simplemente defina el método con la firma correcta.
Solución disponible después de 3 intentos
¿Cómo se declara que el tipo P implementa la interfaz Greeter?
type P struct{}
// ?Resumen
- Interfaz = conjunto de firmas de métodos; sin CÓDIGOPH0.
- Implementación implícita: solo tenga los métodos con la firma correcta.
- Idiomatic: interfaces pequeñas (1–2 métodos), nombres en
-er. interface{}/any: acepta cualquier valor, pierde seguridad de tipo.- Conjunto de métodos: receptor de puntero → solo
*Tsatisface la interfaz. - Ir al polimorfismo: parámetros escritos en la interfaz, sin jerarquías.