• [^] # Re: simple ?

    Posté par (site web personnel) . En réponse au journal Rust en version 0.12. Évalué à 2. Dernière modification le 16 octobre 2014 à 12:20.

    La composition anonyme est juste une "astuce" pour avoir une forme appauvri d’héritage et eviter les collisions de noms

    Par exemple, pour une struct animal

     struct Animal{
     int size;
     }
    

    un heritage typique est :

     struct Ours: Animal{
     }
     Ours ours;
     print(ours.size)
    

    Une composition serait de faire :

     struct Ours{
     Animal animal_data;
     }
     Ours ours
     print(ours.animal_data.size)
    

    Une composition anonyme en Go ressemble à ça

     struct Ours{
     Animal;
     }
     Ours ours
     print(ours.size)
    

    La principal différence avec l'heritage est que la composition anonyme n'implique pas le polymorphisme.

    Il est impossible en golang de faire qqchose comme :

     struct Arbre{
     virtual msg() { print("hello arbre") }
     }
     struct Tilleul {
     Arbre;
     virtual msg() { print("hello tilleuls") }
     }
     Arbre* a = new Tilleuls()
     a->msg()
     # hello tilleuls
    

    Ça ne marchera simplement pas dans le cas d'une composition anonyme, simplement car la composition n'implique pas le système de vtable qu'a C++ par exemple.
    Mais d'un autre coté, ça permet de composer un objet qui contient plusieurs sous objets de manière completement transparente comme on peut faire en héritage multiple et même si ces objets ont un parent en commun : on s'en fout.

    Pour le polymorphisme, c'est fait en Golang via le concept d'interface et d’héritage structurel et non par type comme en Java.
    C'est assez bien expliqué ici http://golangtutorials.blogspot.ch/2011/06/polymorphism-in-go.html

    Grosso-modo contrairement à Java ou similaire, pour "matcher" une interface, tu n'as pas besoin de l’hériter ou d'en dériver.
    Tout objet possédant une "signature" similaire à celle de l'interface ( une methode Speak() ) dans l’exemple, sera considérer comme un objet parfaitement valide.

    C'est puissant, trés puissant.

    Quand au dernier point à propos de la composition anonyme avec un go-pointer, Ceci l'illustre bien

     type JohnLenon struct {
     nom string
     }
     type JohnLenonEnConcert struct{
     *JohnLenon
     concert string
     }
     func main() {
     john := JohnLenon{"john's name"}
     john_concert := JohnLenonEnConcert{&john, "A paris"}
     fmt.Printf(" nom de john: %s \n", john.nom)
     fmt.Printf(" nom de john en concert : %s \n", john_concert.nom)
     john.nom = "bob";
     fmt.Printf(" nom de john en concert : %s \n", john_concert.nom) 
     }
     nom de john: john's name 
     nom de john en concert : john's name 
     nom de john en concert : bob 
    

    La composition dans ce cas reference un objet déja existant... qui veut etre modifié... cloné... partagé... etc..