De PHP a GO Capitulo 2 - "Objetos"

De PHP a GO Capitulo 2 - "Objetos"

Capitulo Anterior: De PHP a GO - Comienzo


El viejo C tenia razón y es que a lo mejor no se necesitan los objectos tal y como los conocemos para hacer software robusto y por que muy dentro de nosotros sabíamos que en el paradigma orientado a objetos habían ciertos vacíos que los dejamos a la fe para no complicar mas las cosas.

En GO volvemos a las probadas estructuras, las estructuras son un tipo de datos (Si un tipo de datos!), que los permite crear una colección de campos con sus respectivos tipos.

Ya podes ir tirando por la ventana todo los sabias de orientación a objectos!! pero con cuidado que rescataremos un par de cosas.

Las estructuras son muy simples y sencillas de definir y dentro de sus campos pueden tener otras estructuras.

type User struct {
    id int
    firstName string
    lastName string
    age int
}

Y para instanciarlas

 juan := User{1, "Juan", "Millan", 30}

Ya que la creación de la estructura es muy similar a la de los objetos de Javascript yo prefiero por comodidad mental hacerlo con sus claves (y por que se ve mas bonito ñ_ñ).

juan := User{id: 1, firstName: "Juan", lastName: "Millan", age: 30}

Y para acceder a sus campos basta con hacer juan.firstName.

Y los métodos?

Conociendo las ansias ya se estarán preguntando por los métodos, pero no hay nada de que preocuparse GO nos permite crear métodos y vincularlos a las estructuras.

Los métodos se crean fuera de la estructura (no hay que complicar las cosas) y se vinculan con un receptor el receptor se ubica entre la palabra func y la definición de la función.

func ( u User) fullName() string {
    return u.firstName + " " + u.lastName
}

Como podemos ver antes de definir el nombre de nuestro método hemos agregado el receptor u User que vincula la función con la estructura.

Pero ojo al puntero! Jajajajaja

Punteros

El método anterior esta bien pero estamos pasando la estructura por valor y no por referencia por lo que si deseamos modificar algo de la estructura mediante un método necesitamos usar punteros.

Los puntero son una de las características mas poderosas de C que nos permiten llevar el lenguaje a puntos insospechados sobrepasando las barreras de tiempo y el espacio (sacando las referencias desde el registro de memoria).

GO implementa punteros en su definición mas simple, sin la aritmética de punteros ya que de hacerlo podríamos tirarnos por la ventana también!.

Si no has tenido la oportunidad de trabajar con punteros os los explicare de una manera simple.

cuando definimos una variable, estructura etc, para este elemento se crea una referencia en memoria y esta referencia la podemos almacenar en otra variable pero de tipo puntero.

Puede parecer confuso definir una variable de tipo puntero por que el tipo puntero solo es una referencia en memoria, pero puede ser una referencia en memoria de tipo entero, string, bool o strutc por ello a la hora de definirlo ponemos el tipo.

 var punteroInt *int
 var punteroUser *User

Supongamos que definimos la variable nombre := "Juan" en memoria tendrá la siguiente referencia 0xc0000120a0 nosotros podemos almacenar esa referencia en un puntero de la siguiente manera puntero = &nombre y luego si queremos modificar el valor de la variable nombre lo podemos hacer a través del puntero presidiendolo con un asterisco *puntero = "Esteban"

No os preocupes si no se comprende del todo al principio, el conocimiento ira filtrando las capas del cerebro hasta llegar al centro y allí sentirás la iluminación de los punteros.

Volviendo a los métodos de nuestra estructura creemos uno que si nos permita modificar lo valores de esta.

func (p *User ) birthday()  {
     p.age ++
}

De esta manera cada vez que se llame el método juan.birthday() tendré un año mas!

Y ya me preguntaran y por que no usaste en el método *p.age ++ y.. GO sabrá como hacer sus cosas!, esto sucede por estamos accediendo a la propiedad age GO detecta automáticamente que se trata del elemento que hay detrás de la referencia en memoria.

Interfaces

Si hay algo que funciona perfectamente en el paradigma orientado a objetos son las interfaces esa capacidad de hacer las cosas modulares e intercambiables es sin lugar a dudas uno de los grandes aciertos.

En PHP una interfaz es un contrato que obliga a la clase que la implementa a cumplir con una serie de métodos, en muchas ocasiones nos hemos visto rellenar métodos vacíos solo para cumplir con un contrato ya que a lo mejor solo vamos a usar una de ellos en nuestra implementación.

En GO las interfaces no condicionan a las estructuras, de esa manera la modularidad es mucho mas amplia ya que cuando definimos un parámetro del tipo de una interfaz, a la hora de pasar el valor del parámetros se validara que cuente con los métodos definidos en la interfaz.

Por lo general las interfaces en GO se definen con la terminación "er" sin importar las raras combinaciones que se puedan llegar a dar.

type Executer interface {
      execute()
}

Una vez definida la interfaz solo basta con que vinculemos a la estructura un método con la misma firma.

type MyRequest struct {
    command func()
}

func (t MyRequest) execute() {
    t.command()
}

Y esta ya podrá ser usada donde se haya definido un parámetro del tipo Executer.

También podemos crear interfaces que contengan a otras esto nos brinda la posibilidad de hacerlas muy simples y reutilizables

type Reader interface {
    Read(b []byte) (n int, err error)
}

type Writer interface {
    Write(b []byte) (n int, err error)
}

type ReadWriter interface {
    Reader
    Writer
}

Siguente Capitulo: De PHP a GO Capitulo 3 - Arreglos


Ya sabes que me podes dejar comentarios aquí o escribirme por twitter a @millancore