Silex v0.47.1 / Docs Source canonique ↗

Créer une valeur nominale avec une structure

Une structure définit un type valeur avec des champs nommés. Une affectation ordinaire copie sa valeur.

struct Position {
    var x:int
    var y:int = 10
}

func main() {
    let origin = Position()
    var cursor = Position(x:2, y:3)
    var target = Position()
        ..x = 10
        ..y = 5

    cursor.x = 4

    print(origin.y)
    print(cursor.x)
    print(target.x)
    print(target.y)
}

Sans constructeur personnalisé, les champs sont nommés et peuvent apparaître dans n'importe quel ordre. Un champ omis reçoit d'abord sa valeur déclarée, puis à défaut la valeur intrinsèque de son type. Ici, la cascade configure target juste après sa création. Le programme affiche successivement 10, 4, 10 et 5.

La valeur déclarée après = accepte une expression ordinaire, y compris un appel de fonction ou une cascade. Silex l'évalue dans l'ordre des champs pour chaque nouvelle valeur : une liste ou une autre ressource ainsi créée n'est pas partagée accidentellement entre deux constructions. Cette expression n'a accès ni à self ni aux paramètres d'un constructeur.

Copier une structure

var first = Position(x:1, y:2)
var second = first

second.x = 10
print(first.x) // 1

Les structures sont nominales : deux déclarations distinctes créent deux types distincts, même avec les mêmes champs. Leur affectation copie récursivement les champs. Un champ de classe continue toutefois de désigner la même instance partagée. Utilisez copy lorsque tout le graphe atteignable doit être détaché.

Établir un invariant avec init

struct Position {
    let x:int
    let y:int

    init(value:int) {
        self.x = value
        self.y = value
    }
}

let point = Position(5)

Déclarer un seul init ferme l'initialiseur automatique par champs nommés. Chaque champ let sans valeur déclarée doit alors être initialisé exactement une fois sur chaque chemin normal du constructeur. Il en va de même pour un champ var dont le type ne fournit ni valeur intrinsèque ni construction sans argument. Les champs déjà initialisés peuvent être lus pour calculer les suivants, mais self ne peut être utilisé dans son ensemble qu'après leur initialisation complète.

Une expression de champ convient aux valeurs indépendantes des arguments, init aux invariants qui en dépendent, et l'initialiseur automatique par champs nommés aux valeurs que l'appelant doit choisir. Un type optionnel reste réservé à une absence valide dans le modèle, pas au stockage provisoire d'un champ en cours de construction.

Ajouter des méthodes

struct Counter {
    var value:int

    func increment(amount:int = 1) {
        self.value += amount
    }

    func current() int {
        return self.value
    }
}

Une méthode reçoit self implicitement. Silex déduit si elle le modifie ; un appel modifiable exige un récepteur déclaré avec var.

Un membre qui calcule ou contrôle son accès se déclare comme une propriété. Il ne devient pas pour autant un paramètre de l'initialiseur automatique par champs nommés.

Imbriquer un type

public struct Catalog {
    struct Entry {
        let value:int
    }
}

let entry = Catalog.Entry(value:42)

Un type imbriqué ne capture aucune instance du conteneur. Un alias ou une réexportation publique du type extérieur conserve l'accès à ses types imbriqués : un alias Window expose donc aussi Window.Settings.

Les membres statiques, les structures génériques et leur nettoyage possèdent leurs pages dédiées afin de ne pas mélanger ces contrats avec la sémantique de valeur ordinaire.

Revenir aux types de données · Partager une identité avec une classe