• 27/07/2024 4:19 AM

Interfaces

porJesus Flores

Sep 23, 2021

En este post vamos a tratar el manejo de Interfaces, las interfaces son un tipo abstracto que describe los métodos a implementarse en una estructura así como la respectiva firma de cada uno.

En otras palabras una interfaz es como un plano o protocolo que indica los métodos que es necesario satisfacer, cuando una estructura satisface una interfaz se puede decir que la ha implementado.

Declarar Interfaces

Para crear interfaces en Go se utiliza la palabra reservada interface, seguida de una lista, con los nombres de los métodos y sus respectivos parámetros y valores de retorno, en caso de devolver valores.

//Se declara la interfaz y solo se realiza la declaracion de los metodos
//no tienen implementación ni cuerpo
type Alumno interface {
	//Este método regresará en un string
	ImprimirNombre() string 
	//Este método esperará un int como parámetro               			
	ImprimirNombreEscuela(idAlumno int)
	//Este método espera 2 parámetros y retornará un float             
	ImprimirCalificacion(b int, t int) float64 
}

Implementar una Interfaz

Ahora vamos a crear una estructura llamada Alum que satisfaga los métodos requeridos por la interfaz Alumno, por tanto haremos la implementación de los métodos en Alum con la firma indicada en la interfaz.

package main

import "fmt"

type Alumno interface {
	//Métodos a satisfacer-solo hacemos la declaración
	ImprimirNombre()
	ImprimirPromedio(parcial1 int, parcial2 int) int
}

// creamos una estructura con solo 1 propiedad
type Alum struct {
	nombre string
}

// implementamos en la estructura Alum el método ImprimirNombre declarado en la interfaz
func (a Alum) ImprimirNombre() {
	fmt.Println("Nombre del Alumno:\t", a.nombre)
}

// implementamos en la estructura Alum el método ImprimirPromedio declarado en la interfaz
func (a Alum) ImprimirPromedio(parcial1 int, parcial2 int) int {
	return (parcial1 + parcial2) / 2
}

func main() {
	//declaramos a1 como variable Alumno (nuestra interface)
	var a1 Alumno
	//ahora creamos Alum y le asignamos el valor de su propiedad nombre
	a1 = Alum{"kobe"}
	//por ultimo ahora podemos utilizar los métodos en a1
	a1.ImprimirNombre()
	fmt.Println("Promedio del Alumno: ", a1.ImprimirPromedio(5, 9))
}

Interfaces y Direcciones de Memoria

Si un método acepta un valor de cierto tipo, la interfaz debe recibir ese mismo tipo de valor, por tanto si un método tiene un apuntador, la interfaz debe recibir la dirección de la variable de acuerdo al tipo de dato que espera.
Veamos un ejemplo:

package main

import "fmt"

//Declaramos una estructura con 2 propiedades marca y modelo
type Computadora struct {
	marca, modelo string
}

//Declaramos una interfaz con el método imprimir como contrato
type Funciones interface {
	Imprimir()
}

//agregamos un método a la estructura computadora
//esperando como apuntador la estructura(referencia)
func (c *Computadora) GuardarValores(marca, modelo string) {
	c.marca = marca
	c.modelo = modelo
}

//satisfacemos la interfaz al utilizar el método imprimir en la estructura
//de igual modo esperamos un apuntador
func (c *Computadora) Imprimir() {
	fmt.Printf("Marca: %s, Modelo: %s\n", c.marca, c.modelo)
}

func main() {
	//creamos un objeto del tipo computadora
	var c Computadora
	//asignamos valores a las propiedades mediante el método GuardarValores
	c.GuardarValores("Dell", "DELL INSPIRON")

	var f Funciones // Declaramos f del tipo Funciones(interfaz)
	f = &c          // asignamos las dirección de nuestro objeto computadora
	f.Imprimir()    // ahora podemos utilizar el método imprimir desde la interfaz
}

Interfaces Vacías

Las interfaces vacías como son conocidas las estructuras del tipo interface{} en golang son utilizadas para trabajar con cualquier tipo de valores, las interfaces vacías no cuentan con métodos que sean necesario satisfacer, por tanto cualquier tipo de datos o estructura las satisface.

package main

import "fmt"

//declaramos un método que espera un valor del tipo interfaz vacía
//dentro del método imprimimos la interfaz
func imprimir(i interface{}) {
	fmt.Println(i)
}

func main() {
	//declaramos un variable del tipo de dato interfaz vacía
	var interfazVacia interface{}
	//asignamos un valor entero
	interfazVacia = 50
	imprimir(interfazVacia)

	//asignamos un valor flotante
	interfazVacia = 126.26
	imprimir(interfazVacia)

	//asignamos un string
	interfazVacia = "Madrid"
	imprimir(interfazVacia)

	//declaramos un slice
	var ciudades = []string{"cadiz", "mallorca", "ibiza"}
	imprimir(ciudades)

	//declaramos un map
	var jugadores = map[string]int{"CR7": 36, "MESSI": 34}
	imprimir(jugadores)

}

Como podemos ver, es posible asignar cualquier tipo de valor a una interfaz vacía e imprimir su valor dentro del método imprimir.

por Jesus Flores

Ingeniero de Software y Agile Coach

Deja un comentario

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