Structures

Une des façons de définir nos propres types en D est de définir une struct:

struct Person
{
    int age;
    int height;
    float ageXHeight;
}

Une struct est toujours construite sur la pile (à moins qu'elle soit appelée avec new) et est copiée par valeur lorsqu'elle est passée en paramètre à une fonction.

auto p = Person(30, 180, 3,1415);
auto t = p; //copie

Quand un nouvel objet struct est créé, ses membres peuvent être initialisés dans l'ordre dans lequel ils sont définis dans la struct. On peut définir un constructeur personnalisé en créant une méthode this(...). En cas de conflits de nom, on peut accéder à la structure courante grâce à this:

struct Person 
{
    this(int age, int height)
    {
        this.age = age;
        this.height = height;
        this.ageXHeight = cast(float)age * height;
    }
}

//...

Person p(30, 100); //initialisation
p = Person(30, 180); //assignation à une nouvelle instance

Une struct peut contenir n'importe quel nombre de méthodes. Ces méthodes sont public par défaut, et donc accessibles depuis l'extérieur. Elles peuvent être private et donc n'être accessibles que depuis une autre méthode de la même struct, ou d'un autre endroit dans le même module.

struct Person
{
    void faireQqch()
    {
        //...
    }

    private void faireChosePrivee()
    {
        //...
    }
} 

//...

p.faireQqch(); // Appel de la méthode faireQqch
p.faireChosePrivee(); // Interdit

Méthodes const

Si une méthode est déclarée avec const, elle ne sera pas autorisée à modifier un membre de la structure. C'est une garantie offerte par le compilateur. Déclarer une méthode const permet de l'appeler sur un objet const ou immutable, mais garantie également aux appelants que la méthode ne changera pas l'état de l'objet.

Méthodes statiques

Si une méthode est déclarée static, on pourra l'appeler sans objet instancié (par exemple Person.methodeStatique()) mais elle ne sera pas autorisée à accéder à des membres non-statiques. Cela peut être utilisé si une méthode n'a pas besoin d'accéder à un membre non-static de la structure, mais est lié logiquement à cette structure. Cela peut aussi être utilisé pour offrir une fonctionnalité sans créer d'instance explicite, par exemple, certains implémentations du patron de conception Singleton utilisent static.

Héritage

Une struct ne peut pas hériter d'une autre struct. Des hiérarchies de types ne peuvent être construites qu'avec des classes, que nous verrons dans une prochaine aprtie. Cependant, avec alias this ou les mixins, on peut facilement obtenir du polymorphisme.

Pour aller plus loin

Exercice

À partir de struct Vector3, implémentez les fonctions suivantes et faites fonctionner l'exemple correctement:

  • length() - retourne la longueur du vecteur
  • dot(Vector3) - retourne le produit scalaire avec ce vecteur
  • toString() - retourne la représentation de ce vecteur sous forme de string

La fonction std.string.format retourne une chaîne de caractères en utilisant une syntaxe similaire à celle de printf: format("MonEntier = %d", monEntier). Les chaînes de caractères seront expliquées plus en détails dans une prochaine partie.

rdmd playground.d