¿Por qué Golang prefiere la composición a la herencia?

Nov 06 2022
Go generalmente se promociona como un lenguaje orientado a objetos, pero es algo más detrás de escena. Normalmente, en los lenguajes orientados a objetos se usa la herencia, pero en Go se prefiere la composición, he aquí por qué: Problemas con la herencia: (i) Grandes jerarquías (ii) Acoplamiento estrecho Hablemos sobre la herencia: Herencia: Corresponde a las relaciones "es un".

Go generalmente se promociona como un lenguaje orientado a objetos, pero es algo más detrás de escena. Normalmente, en los lenguajes orientados a objetos se usa la herencia, pero en Go se prefiere la composición, he aquí por qué:

Problemas con la herencia:

(i) Grandes jerarquías (ii) Acoplamiento estrecho

Hablemos de la herencia:

Herencia:

Corresponde a las relaciones “es un”. Tomemos un ejemplo de un animal que tiene los atributos de comer y dormir. Entonces, las posibles clases heredadas de animal pueden ser perro, persona y pez. Los atributos actuales pueden ir bien con las clases heredadas, pero si se agrega un atributo de caminar a los atributos actuales, ¿crees que esto iría bien? La respuesta simple es "No", ya que el pez no tiene la capacidad de caminar. una solución simple podría ser crear categorías para cada tipo si aún queremos usar la herencia. Se vería algo como esto:

El problema con esto es que cada vez que queramos agregar un nuevo atributo, tendríamos que agregarlo a las clases ya definidas. Aquí es donde entra la composición:

Composición:

Corresponde a la relación “tiene una”. Ahora podemos definir los atributos de tal manera que el animal tenga la capacidad de mantenerse "vivo", lo que significa que puede comer y dormir, también podemos definir los atributos para caminar y nadar según la capacidad que el animal debería tener. Como mantener las relaciones "tiene un" es más fácil que mantener las relaciones "es un", es por eso que se prefiere la composición en Go.

Así es como se puede implementar la composición en Go:

package main

import "fmt"

type alive struct {
}
type walkable struct {
}
type swimable struct {
}
type duck struct {
a alive
w walkable
s swimable
}

func (d duck) eat() {
d.a.eat()
}
func (d duck) sleep() {
d.a.sleep()
}
func (d duck) walk() {
d.w.walk()
}
func (d duck) swim() {
d.s.swim()
}
func (alive) eat() {
fmt.Println("Alive and eating")
}
func (alive) sleep() {
fmt.Println("Alive and sleeping")
}
func (walkable) walk() {
fmt.Println("strolling through")
}
func (swimable) swim() {
fmt.Println("Taking a dip")
}
func main() {
d := duck{}
d.eat()
d.sleep()
d.walk()
d.swim()
}

      
                

© Copyright 2021 - 2022 | unogogo.com | All Rights Reserved