08 - Les interfaces et le polymorphisme en Go

Bien qu’en Go, la notion de programmation orientée objet soit assez limitée (pas de réel héritage, pas de vraie encapsulation, …), il est possible de manière assez simple de créer des interfaces et de les implémenter. Cela permet entre autres de manipuler indifféremment des objets de divers types, ou encore d’assurer un contrat pour un type donné : on assure que ce dernier dispose des méthodes requises. Attention toutefois, en POO, il convient de respecter un principe clé : le LSP (Liskov Substitution Principle).


Le code source écrit dans cet épisode :

package main

import "fmt"

type printable interface {
  print() string
}

type todoList []*todo

func (tl todoList) print() string {
  var str string
  str = fmt.Sprintf("Type : TodoList \nTaille : %d\n", len(tl))
  str = fmt.Sprintf("%s\n\%s", str, "---------------------------------")
  for idx, t := range tl {
    str = fmt.Sprintf("%s\n[%d] : %s", str, idx+1, t.text)
  }
  return str
}

type todo struct {
  text string
  done bool
}

// function with receiver
// func (receiver) identifier(args) (returns)
func (t *todo) toggle() {
  t.done = !t.done
}

type user struct {
  name  string
  todos []*todo
}

func (u user) show() {
  fmt.Printf("Name : %s\n", u.name)
  fmt.Printf("Todos: %d\n", len(u.todos))

  for _, t := range u.todos {
    fmt.Printf("<Todo text=%s done=%v>\n", t.text, t.done)
  }
}

func (u *user) addTodo(t *todo) {
  u.todos = append(u.todos, t)
}

func main() {
  u := user{name: "Kurosoki ichigo"}

  t := todo{text: "Bien faire les choses cette fois."}
  t.toggle()
  u.addTodo(&t)

  u.show()
  t.toggle()

  u.show()
}