Orientación a Objetos en Go

jaimeiherrera

Jaime Herrera Muñoz

Posted on January 3, 2024

Orientación a Objetos en Go

¿Es Go un lenguaje orientado a objetos? ¿Es posible pober en practica la orientación a objetos en Go?

¿Qué es la POO?

En palabras simples: Paradigma de programación que se basa en el concepto de objetos. Un objeto es una entidad que tiene un estado y un comportamiento. El estado de un objeto se representa mediante sus atributos, mientras que su comportamiento se representa mediante sus métodos.

La POO permite dividir el programa en unidades más pequeñas con el fin de facilitar el desarrollo, mantenimiento y reutilización. Ademas de poder modelar el mundo real de manera más natural.

Ventajas y Desventajas de la POO

Ventajas

  • Reutilización de código: La POO permite reutilizar el código de las clases ya existentes, lo que ahorra tiempo y esfuerzo de desarrollo.
  • Claridad y legibilidad del código: La POO ayuda a organizar el código de una manera clara y legible, lo que facilita su comprensión y mantenimiento.
  • Escalabilidad: La POO permite crear sistemas más complejos y escalables.
  • Agilidad: La POO ayuda a agilizar el desarrollo de software, ya que permite dividir el trabajo en unidades más pequeñas y fáciles de manejar.

Desventajas

  • Complejidad: La POO puede ser un paradigma complejo de aprender y dominar.
  • Costo: La POO requiere un mayor esfuerzo de desarrollo que otros paradigmas de programación.

Conceptos Principales de la POO

  • Abstracción: Representación de la realidad en forma de clases y objetos.
    • Clase: Es un molde o plantilla para crear objetos. Una clase define los atributos y métodos de un objeto.
    • Objeto: Es una instancia de una clase. Un objeto tiene un estado y un comportamiento que están definidos por la clase de la que es instancia.
    • Atributo: Es una variable que representa una característica o propiedad de un objeto.
    • Método: Es una función que representa una acción que puede realizar un objeto.
  • Encapsulamiento: Es el ocultamiento de los detalles de implementación de un objeto.
  • Herencia: Es la capacidad de un objeto para heredar los atributos y métodos de otro objeto.
  • Polimorfismo: Es la capacidad de un objeto para comportarse de forma diferente en función del contexto.

Como se Aplican los Conceptos en Go

  • Abstracción
    • Clases: En Go, las clases pasan a ser las structs. Las structs son tipos de datos que pueden contener atributos y métodos.
    • Objetos: En Go, los objetos son instancias de las structs.
    • Atributos: En Go, los atributos son las variables declaradas en las structs.
    • Métodos: En Go, los métodos son funciones que se declaran dentro de las structs.
  • Encapsulamiento: En Go, el encapsulamiento se logra utilizando los modificadores de acceso (como cuando el nombre de una variable o método empieza con la primera letra a mayúscula o minúscula).
  • Herencia: En Go, la herencia no se admite directamente. Sin embargo, se puede lograr mediante:
    • Composición: Structs dentro de otros structs.
    • Interfaces: Declarando las func que necesitamos heredar y posteriormente implementado structs que cumplan con la interfaz
  • Polimorfismo: En Go, el polimorfismo se logra mediante la interfaz. Las interfaces definen un conjunto de métodos que deben implementarse. De esta forma, varios structs pueden cumplir con los requisitos de la interfaz.

POO en Go en la Practica

Podemos representar la orientación a objetos en alto nivel con los siguientes dibujos:
Representación grafica de una entidad

Abstracción (Entidades u Objetos)

Por lo anterior podemos deducir de los objetos como tal lo siguiente: a grandes rasgos y a primera vista, la gran diferencia está entre las structs y las clases. Esto en la practica esta diferencia sería:

  • Otros lenguajes: Se declara el comportamiento del objeto dentro de su misma estructura de clases.
  • Go: Su comportamiento se asocia a una struct en particular.

Para el siguiente ejemplo, definamos un objeto persona que tiene como atributos un Nombre y una Edad, ademas que como comportamiento pueda Saludar.

C Sharp

class Persona
{
    public string Nombre { get; set; }
    public int Edad { get; set; }

    public void Saludar()
    {
        Console.WriteLine($"Hola, soy {Nombre} y tengo {Edad} años.");
    }
}
Enter fullscreen mode Exit fullscreen mode

Python

class Persona:
    def __init__(self, nombre, edad):
        self.Nombre = nombre
        self.Edad = edad

    def Saludar(self):
        print(f"Hola, soy {self.Nombre} y tengo {self.Edad} años.")
Enter fullscreen mode Exit fullscreen mode

Go

type Persona struct {
    Nombre string
    Edad   int
}

func (p Persona) Saludar() {
    fmt.Printf("Hola, soy %s y tengo %d años.\n", p.Nombre, p.Edad)
}
Enter fullscreen mode Exit fullscreen mode

Para todos estos ejemplos, el objeto persona será el siguiente:
Image description

Encapsulamiento

Mientras que en otros lenguajes podemos encapsular un atributo o un método mediante la palabra reservada “private”, en lenguajes como Go o Python se hace mediante convenciones. En el caso de Go basta solo con escribir la primera letra de un método o atributo en minúscula.

C Sharp

class Persona
{
    private string Nombre { get; set; }
    private int Edad { get; set; }

    private void Saludar()
    {
        Console.WriteLine($"Hola, soy {Nombre} y tengo {Edad} años.");
    }
}
Enter fullscreen mode Exit fullscreen mode

Python

class Persona:
    def __init__(self, nombre, edad):
        self._Nombre = nombre
        self._Edad = edad

    def _Saludar(self):
        print(f"Hola, soy {self._Nombre} y tengo {self._Edad} años.")
Enter fullscreen mode Exit fullscreen mode

Go

type Persona struct {
    nombre string
    edad   int
}

func (p Persona) saludar() {
    fmt.Printf("Hola, soy %s y tengo %d años.\n", p.nombre, p.edad)
}
Enter fullscreen mode Exit fullscreen mode

Composición y Herencia

En Go no existe algo tal como las herencias, para esto podemos usar la composición para incorporar una Struct dentro de otra.

C Sharp

class Persona
{
    private string Nombre { get; set; }
    private int Edad { get; set; }

    private void Saludar()
    {
        Console.WriteLine($"Hola, soy {Nombre} y tengo {Edad} años.");
    }
}

class Trabajador : Persona
{
  private int ID { get; set; }
}
Enter fullscreen mode Exit fullscreen mode

Python

class Persona:
    def __init__(self, nombre, edad):
        self._Nombre = nombre
        self._Edad = edad

    def _Saludar(self):
        print(f"Hola, soy {self._Nombre} y tengo {self._Edad} años.")

class Trabajador(Persona):
  pass
Enter fullscreen mode Exit fullscreen mode

Go

type Persona struct {
    Nombre string
    Edad   int
}

type Trabajador struct {
  Persona
  ID      int
}

func (p Persona) Saludar() {
    fmt.Printf("Hola, soy %s y tengo %d años.\n", p.Nombre, p.Edad)
}
Enter fullscreen mode Exit fullscreen mode

Polimorfismo

El polimorfismo en Go se puede hacer a travez de interfaces. Estas interfaces pueden ser implementadas por cualquier struct que cumpla con sus condiciones.

C Sharp

using System;

// Clase base (Superclase)
class Animal
{
  public virtual void HacerSonido()
  {
    Console.WriteLine("El animal hacer un sonido");
  }
}

// Clase derivada
class Perro : Animal
{
  public override void HacerSonido()
  {
    Console.WriteLine("El perro ladra");
  }
}

// Clase derivada
class Gato : Animal
{
  public override void HacerSonido()
  {
    Console.WriteLine("El gato maulla");
  }
}

class Program
{
  static void Main
  {
    // Crea objetos de diferentes clases
    Animal MiAnimal = new Animal();
    Animal MiPerro = new Perro();
    Animal MiGato = new Gato();

    MiAnimal.HacerSonido(); // "El animal hacer un sonido"
    MiPerro.HacerSonido(); // "El perro ladra"
    MiGato.HacerSonido(); // "El gato maulla"
  }
}
Enter fullscreen mode Exit fullscreen mode

Python

# Clase base
class Animal:
  def hacer_sonido(self):
    pass

# Clase derivada
class Perro(Animal):
  def hacer_sonido(self):
    return "El perro ladra"

# Clase derivada
class Gato(Animal):
  def hacer_sonido(self):
    return "El gato maulla"

# Función que utiliza polimorfismo
def hacer_sonido_animal(animal):
  return animal.hacer_sonido()

# Crea objetos de diferentes clases
mi_animal = Animal()
mi_perro = Perro()
mi_gato = Gato()

print(hacer_sonido_animal(mi_animal)) # No imprime nada
print(hacer_sonido_animal(mi_perro)) # "El perro ladra"
print(hacer_sonido_animal(mi_gato)) # "El gato maulla"
Enter fullscreen mode Exit fullscreen mode

Go

package main

import "fmt"

type Animal interface {
  HacerSonido() string
}

type Perro struct{}

func (p Perro) HacerSonido() string {
  return "El perro ladra"
}

type Gato struct{}

func (g Gato) HacerSonido() string {
  return "El gato maulla"
}

func HacerSonidoAnimal(a Animal) string {
  fmt.Println(a.HacerSonido())
}

func Main() {
  miPerro := Perro{}
  miGato := Gato{}

  HacerSonidoAnimal(miPerro) // "El perro ladra"
  HacerSonidoAnimal(miGato) // "El gato maulla"
}
Enter fullscreen mode Exit fullscreen mode

Recordar que las interfaces son satisfacidas solo si el struct que se implementa tiene las mismas func que la interfaz.

En Conclusión

Go no es un lenguaje orientado a objetos tradicional, pero si se puede trabajar con la orientación a objetos. Como pudimos ver en las secciones anteriores, podemos adaptar los conceptos principales de la POO con las herramientas que nos entrega Go.

💖 💪 🙅 🚩
jaimeiherrera
Jaime Herrera Muñoz

Posted on January 3, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related

Orientación a Objetos en Go
go Orientación a Objetos en Go

January 3, 2024