Interfaces en Go (Golang)

in #cervantes6 years ago (edited)

gopher wallpaper

<h1>Interfaces en Go <p dir="auto"><em>Hace poco conocimos las estructuras, los métodos y los tipos de datos personalizados, si aún no lees esas publicaciones te recomiendo que pases primero por ellas y luego regreses aquí. De cualquier forma, esta vez es el turno de las interfaces, un tipo de dato bastante flexible interesante. <h2>¿Que son las interfaces? <blockquote> <p dir="auto">Aunque Go no se considera generalmente un lenguaje orientado a objetos, permite que los métodos se definan en tipos definidos por el usuario. Go tiene tipos de "interfaz" que son compatibles con cualquier tipo que soporta un conjunto dado de métodos (el tipo no necesita implementar explícitamente la interfaz). La interfaz vacía, interface {}, es compatible con todos los tipos.<br /> Fuente: <a href="https://es.wikipedia.org/wiki/Interfaz_(programaci%C3%B3n)" target="_blank" rel="nofollow noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">Wikipedia <p dir="auto">Entendamos primero que las <em>interfaces son otro tipo de dato en <strong>Go, nos permite establecer la firma de un conjunto de métodos vacíos, que debemos definir en el tipo de dato en el que deseemos implementar la interfaz, si vienen de lenguajes orientados a objetos es posible que esto les parezca familiar, de cualquier forma quedará más claro después de que las veamos en acción. <h2>Interfaces en acción <pre><code>package main import "fmt" type Persona struct { Nombre string Apellido string Edad uint8 } type Programador struct { Persona Especialidad string LenguajesFavoritos []string } func (p Persona) Saludar() { fmt.Printf("Hola, mi nombre es %s %s y tengo %d años\n", p.Nombre, p.Apellido, p.Edad) } func (p *Persona) Cumpleanios() { p.Edad += 1 } func (p Programador) beberCafe() { fmt.Println("¡Me siento vivo!") } func main() { p := Programador{ Persona{"Orlando", "Monteverde", 26}, "Desarrollo Web", []string{"Go", "Python", "JavaScript"}, } p.Saludar() } <p dir="auto"><br /><br /> Retomando el ejemplo de la <a href="https://steemit.com/cervantes/@orlmicron/estructuras-las-clases-de-go-golang" target="_blank" rel="nofollow noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">publicación anterior, nada nuevo que mencionar. Ahora crearemos un par de variables de tipo <code>Persona, y usaremos también su método saludar. <pre><code>… func main() { p1 := Programador{ Persona{"Orlando", "Monteverde", 26}, "Desarrollo Web", []string{"Go", "Python", "JavaScript"}, } p2 := Persona{"Daniel", "Herrera", 32} p3 := Persona{"Carmen", "Salazar", 20} p1.Saludar() // Hola, mi nombre es Orlando Monteverde y tengo 26 años p2.Saludar() // Hola, mi nombre es Daniel Herrera y tengo 32 años p3.Saludar() // Hola, mi nombre es Carmen Salazar y tengo 20 años } <p dir="auto"><br /><br /> Al ser <code>p2 y <code>p3 del tipo <code>Persona, tienen acceso al método <code>Saludar, de igual forma <code>p1, que es del tipo <code>Programador, al contener al tipo persona como <em>campo anónimo también tiene acceso a dicho método, como vimos en la <a href="https://steemit.com/cervantes/@orlmicron/estructuras-las-clases-de-go-golang" target="_blank" rel="nofollow noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">publicación anterior, por lo que el resultado no debería sorprendernos. Por el momento son sólo tres variables, pero esta forma de llamar al método <code>Saludar se vuelve tediosa y difícil de mantener si tuviéramos más, la solución más evidente sería recurrir a un ciclo. Entonces coloquemos las variables en un <code>slice, podríamos pensar en hacer lo siguiente. <pre><code>... func main() { p1 := Programador{ Persona{"Orlando", "Monteverde", 26}, "Desarrollo Web", []string{"Go", "Python", "JavaScript"}, } p2 := Persona{"Daniel", "Herrera", 32} p3 := Persona{"Carmen", "Salazar", 20} vecinos := []Persona{p1, p2, p3} for _, v := range vecinos { v.Saludar() } } <p dir="auto"><br /><br /> Si intentan compilar se encontrarán con un error, el compilador es bastante específico, nos dirá que no se puede usar <code>p1 del tipo <code>Programador como tipo <code>Persona. <code>Programador tiene una estructura <code>Persona dentro, pero en sí mismo no es una variable del tipo <code>Persona. Una solución a este problema son las interfaces. Veamos como definir una. <pre><code>... type Vecino interface { Saludar() } ... <p dir="auto"><br /><br /> Notarán que la sintaxis es similar a las <em>Estructuras, básicamente reemplazamos el tipo <code>struct por <code>interface. En lo que respecta al cuerpo de la <em>interfaz, no definimos campos, como en las <em>estructuras, definimos método vacíos, más específicamente la firma de ese método. Ahora veamos como utilizarla. <pre><code>... func main() { p1 := Programador{ Persona{"Orlando", "Monteverde", 26}, "Desarrollo Web", []string{"Go", "Python", "JavaScript"}, } p2 := Persona{"Daniel", "Herrera", 32} p3 := Persona{"Carmen", "Salazar", 20} vecinos := []Vecino{p1, p2, p3} for _, v := range vecinos { v.Saludar() } } <p dir="auto"><br /><br /> Con esto obtenemos las misma salida de antes. Ahora, es posible que se pregunten en que momento especificamos que <code>Persona y <code>Programador <em>implementan la <em>interfaz <code>Vecino. La respuesta es simple, no lo hacemos, al menos no explícitamente. <p dir="auto">La <em>Interfaz <code>vecino establece un <em>método llamado <code>Saludar, que no recibe argumentos ni retorna algún valor, el tipo <code>Persona posee un <em>método <code>Saludar que satisface a la <em>interfaz, y Programador, que tiene el tipo <code>Persona como <em>campo anónimo comparte ese método. En resumen, ambos tipos satisfacen a la <em>Interfaz <code>Vecino y por lo tanto pueden usarse como tipo <code>Vecino, así de sencillo, al estilo <strong>Go. El siguiente ejemplo debería dejarlo más claro. <pre><code>... func main() { p1 := Programador{ Persona{"Orlando", "Monteverde", 26}, "Desarrollo Web", []string{"Go", "Python", "JavaScript"}, } p2 := Persona{"Daniel", "Herrera", 32} p3 := Persona{"Carmen", "Salazar", 20} var vecino Vecino vecino = p1 fmt.Println(vecino) // {{Orlando Monteverde 26} Desarrollo Web [Go Python JavaScript]} vecino = p2 fmt.Println(vecino) // {Daniel Herrera 32} vecino = p3 fmt.Println(vecino) // {Carmen Salazar 20} } <p dir="auto"><br /><br /> Ahora declaramos una variable <code>vecino del tipo <code>Vecino, y esta almacena sin problemas a las variables de tipo <code>Persona y <code>Programador, y esto sólo por el hecho de satisfacer a la interfaz. Por otra parte, recordemos que el tipo <code>Programador tiene un método propio llamado <code>beberCafe(), los invito a intentar llamar a ese método desde la variable vecino cuando esta almacena el valor de <code>p1, eso se los dejo de tarea. <p dir="auto">Todavía quedan muchas cosas interesantes sobre las interfaces que iremos viendo en futuras publicaciones, por el momento es suficiente para que puedan incorporar este tipo de dato a sus programas de <strong>Go. Pero siempre es recomendable dar una vuelta por el <a href="https://tour.golang.org/" target="_blank" rel="nofollow noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">gotour y la <a href="https://golang.org/doc/" target="_blank" rel="nofollow noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">documentación oficial del lenguaje. <p dir="auto"><center><img src="https://images.hive.blog/768x0/https://cdn.steemitimages.com/DQmXF55A7pDHvVu4K73h6TgCoH5UpC1WUHFAFhn76NUVgUC/separator.png" alt="separator.png" srcset="https://images.hive.blog/768x0/https://cdn.steemitimages.com/DQmXF55A7pDHvVu4K73h6TgCoH5UpC1WUHFAFhn76NUVgUC/separator.png 1x, https://images.hive.blog/1536x0/https://cdn.steemitimages.com/DQmXF55A7pDHvVu4K73h6TgCoH5UpC1WUHFAFhn76NUVgUC/separator.png 2x" /> <h2>Publicaciones relacionadas <ol> <li><p dir="auto"><a href="https://steemit.com/cervantes/@orlmicron/de-python-a-go-golang" target="_blank" rel="nofollow noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">De Python a Go (Golang) <li><p dir="auto"><a href="https://steemit.com/cervantes/@orlmicron/introduccion-al-lenguaje-de-programacion-go-golang" target="_blank" rel="nofollow noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">Introducción al lenguaje de programación Go (Golang) <li><p dir="auto"><a href="https://steemit.com/cervantes/@orlmicron/estructuras-de-control-de-flujo-en-go" target="_blank" rel="nofollow noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">Estructuras de control de flujo en Go <li><p dir="auto"><a href="https://steemit.com/cervantes/@orlmicron/array-y-slice-en-go-golang" target="_blank" rel="nofollow noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">Array y Slice en Go (Golang) <li><p dir="auto"><a href="https://steemit.com/cervantes/@orlmicron/maps-en-go-golang" target="_blank" rel="nofollow noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">Maps en Go (Golang) <li><p dir="auto"><a href="https://steemit.com/cervantes/@orlmicron/punteros-en-go-golang" target="_blank" rel="nofollow noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">Punteros en Go (Golang) <li><p dir="auto"><a href="https://steemit.com/cervantes/@orlmicron/importaciones-y-paquetes-en-go-golang" target="_blank" rel="nofollow noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">Importaciones y paquetes en Go (Golang) <li><p dir="auto"><a href="https://steemit.com/cervantes/@orlmicron/paquetes-de-terceros-y-alias-en-go-golang" target="_blank" rel="nofollow noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">Paquetes de terceros y alias en Go (Golang) <li><p dir="auto"><a href="https://steemit.com/cervantes/@orlmicron/tipos-de-datos-personalizados-y-metodos-en-go-golang" target="_blank" rel="nofollow noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">Tipos de datos Personalizados y Métodos en Go (Golang) <li><p dir="auto"><a href="https://steemit.com/cervantes/@orlmicron/estructuras-las-clases-de-go-golang" target="_blank" rel="nofollow noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">Estructuras: ¿Las Clases de Go (Golang)? <p dir="auto">Gracias por leer, espero que este artículo te resultara de provecho. Si así fue, no dudes en dejar un <strong>comentario, <strong>compartirlo y <strong>votar. Te invito a comentar cualquier <strong>duda o <strong>sugerencia, te aseguro que las leo todas. Así que, por favor, ayúdame a mejorar y continuar compartiendo contenido de calidad. Si te gusta la programación y/o la informática en general, te invito a formar parte de la comunidad <a href="https://discordapp.com/invite/8cFAFTZ" target="_blank" rel="nofollow noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">Develop Spanish dónde compartimos contenido de esa naturaleza y totalmente en español. Hasta la próxima. <p dir="auto"><img src="https://images.hive.blog/768x0/https://cdn.steemitimages.com/DQmQU5fep6GDnVe1KD4jRgxwD6DcBNvwWPTx82DKBWeciew/banner-steemit.jpg" alt="banner-steemit.jpg" srcset="https://images.hive.blog/768x0/https://cdn.steemitimages.com/DQmQU5fep6GDnVe1KD4jRgxwD6DcBNvwWPTx82DKBWeciew/banner-steemit.jpg 1x, https://images.hive.blog/1536x0/https://cdn.steemitimages.com/DQmQU5fep6GDnVe1KD4jRgxwD6DcBNvwWPTx82DKBWeciew/banner-steemit.jpg 2x" />
Sort:  

Creo que llevas mas avances en tus tutoriales de GO, que yo en los mios de Ruby y Javascript, muy buenos cada uno de tus tutoriales

Este post fue votado por la comunidad y trail @developspanish, comunidad encargada de curar a los programadores, traductores de software y bloggers de informática y tecnología de habla hispana.

¿Quieres recibir mejores recompensas en tus post de informática, tecnología o programación, ayúdanos delegando algo de SP:
1 SP, 5 SP, 10 SP

Ruby. Creo que los míos son muy extensos, por más que intento reducirlos no me sale. ¡Nos leemos!Gracias, @developspanish. Me alegra que te estén gustando los tutoriales. Creo que he avanzado porque me he dedicado exclusivamente a esta serie, aún queda mucho por ver. Y los tuyos son excelentes, concisos al estilo del elegante