web-dev-qa-db-fra.com

Swift constantes: Struct ou Enum

Je ne sais pas lequel des deux convient le mieux pour définir des constantes. Un struct ou un enum. Un struct sera copié chaque fois que je l'utilise ou pas? Quand je pense à un struct avec static let _ constantes cela n'a aucun sens de le copier tout le temps, à mon avis. Mais s'il ne copie pas, alors peu importe ce que je prends?

Quels sont les avantages du choix d'une structure ou d'une énumération?

Francisco dit utiliser Struct.

Ray Wunderlich dit utiliser Enum's. Mais la justification me manque.

66
Paixsn

Les deux structures et les énumérations fonctionnent. À titre d'exemple, les deux

struct PhysicalConstants {
    static let speedOfLight = 299_792_458
    // ...
}

et

enum PhysicalConstants {
    static let speedOfLight = 299_792_458
    // ...
}

travailler et définir une propriété statique PhysicalConstants.speedOfLight.

Re: Un struct sera copié chaque fois que je l'utilise ou pas?

struct et enum sont tous deux des types de valeur, ce qui s'appliquerait également aux énumérations. Mais c'est sans importance ici car vous n'avez pas du tout besoin de créer de valeur: Propriétés statiques (également appelées Les propriétés type ) sont des propriétés du type lui-même et non d'une instance de ce type.

Re: Quels sont les avantages du choix d'une structure ou d'un enum?

Comme mentionné dans le lié-à l'article :

L'avantage d'utiliser une énumération sans casse est qu'elle ne peut pas être instanciée accidentellement et fonctionne comme un espace de noms pur.

Donc pour une structure,

let foo = PhysicalConstants()

crée une valeur (inutile) de type PhysicalConstants, mais pour une énumération sans casse, la compilation est impossible:

let foo = PhysicalConstants()
// error: 'PhysicalConstants' cannot be constructed because it has no accessible initializers
96
Martin R

Voici une réponse courte: Vos constantes doivent-elles être uniques? Ensuite, utilisez une énumération qui l’impose.

Voulez-vous utiliser plusieurs constantes différentes pour contenir la même valeur (souvent utile pour plus de clarté)? Ensuite, utilisez une structure qui le permet.

11
jglasse

Utilisation de Xcode 7.3.1 et Swift 2.2

Bien que je sois d’accord avec Martin R, et que le guide de style de Ray Wenderlich souligne le fait que les énumérations sont meilleures dans presque tous les cas d’utilisation du fait qu’il s’agit d’un pur espace de noms, il existe un endroit où utiliser un struct trumps enums.

Changer de relevé

Commençons par la version de struct:

struct StaticVars {
    static let someString = "someString"
}

switch "someString" {
case StaticVars.someString: print("Matched StaticVars.someString")
default: print("Didn't match StaticVars.someString")
}

En utilisant une structure, cela correspondra et imprimera Matched StaticVars.someString.

Considérons maintenant la version enum sans cas (en changeant seulement le mot clé struct en enum):

enum StaticVars {
    static let someString = "someString"
}

switch "someString" {
case StaticVars.someString: print("Matched StaticVars.someString")
default: print("Didn't match StaticVars.someString")
}

Vous remarquerez que vous obtenez une erreur de compilation lors de l’instruction switch sur le case StaticVars.someString: ligne. L'erreur est Enum case 'someString' not found in type 'String'.

Il existe une pseudo-solution de contournement en convertissant la propriété static en une fermeture qui retourne le type.

Donc, vous voudriez le changer comme ceci:

enum StaticVars {
    static let someString = { return "someString" }
}

switch "someString" {
case StaticVars.someString(): print("Matched StaticVars.someString")
default: print("Didn't match StaticVars.someString")
}

Notez la nécessité de parenthèses dans l'instruction case car c'est maintenant une fonction.

L'inconvénient est que, maintenant que nous en avons fait une fonction, elle est exécutée chaque fois qu'elle est invoquée. Donc, s'il ne s'agit que d'un simple type primitif tel que String ou Int, ce n'est pas si grave. C'est essentiellement une propriété calculée. Si c'est une constante qui doit être calculée et que vous ne voulez la calculer qu'une seule fois, envisagez de la calculer dans une propriété différente et de renvoyer cette valeur déjà calculée dans la clôture.

Vous pouvez également remplacer l'initialiseur par défaut par un privé, puis vous obtiendrez le même type d'erreur de temps de compilation que pour l'énumération sans cas.

struct StaticVars {
    static let someString = "someString"
    private init() {}
}

Mais avec cela, vous voudriez mettre la déclaration de la structure dans son propre fichier, car si vous la déclariez dans le même fichier que, par exemple, une classe View Controller, le fichier de cette classe pourrait toujours instancier accidentellement une image inutile. instance de StaticVars, mais en dehors du fichier de la classe, cela fonctionnerait comme prévu. Mais c'est ton appel.

4
Tim Fuqua