J'ai expliqué le «type d'énumération» la dernière fois, mais cette fois, je vais expliquer le «type d'énumération de type partagé» comme je vous l'ai dit à l'avance.
Il est très étroitement lié à l'article précédent, donc si vous ne l'avez pas encore lu, veuillez également consulter cet article. (https://qiita.com/0901_yasyun/items/a87c49438db68241778b)
Un «type d'énumération de type partagé» est un type qui peut avoir à la fois un «type d'énumération» simple qui ne spécifie pas de «type substantiel» et une structure de plusieurs «tapple» différents. Le but de ce type est de pouvoir traiter plusieurs types de données différents avec un concept commun.
Tout d'abord, voici un aperçu de la définition du «type d'énumération de type partagé». C'est un simple nom de cas «type d'énumération» suivi d'une déclaration «tapple».
nom du type d'énumération{
case Nom du cas Déclaration de type Tupple
case Nom du cas Déclaration de type Tupple
... ...
Voici un exemple de définition concrète. Dans cet exemple, la couleur utilisée pour créer une page Web, etc. est spécifiée par le nom de couleur de la chaîne de caractères, le code de couleur par nombre hexadécimal, etc., mais comme le but de spécifier la couleur est le même dans tous les formats, cela Envisagez d'exprimer avec un type de données.
python
enum WebColor {
case name(String) //Nom de la couleur
case code(String) //Code couleur hexagonal
case white, black, red //Couleurs fréquemment utilisées
}
Vous pouvez utiliser cette définition pour créer diverses instances.
python
let background = WebColor.name("indigo") //Bleu indigo
let turquoise: WebColor = .code("#40E0D0") //Turquoise
let textColor = WebColor = .black //noir
** Les informations décrites dans une structure de type tapple ** sont appelées ci-dessous «informations supplémentaires» ou «charge utile». Vous ne pouvez pas écrire un «type substantiel» dans la définition d'un «type partagé». Le «type de valeur» et le «type d'énumération de type partagé» doivent être décrits comme séparés.
Dans le précédent simple type d'énumération et type d'énumération de type valeur, il était possible de comparer des éléments, mais dans le cas du type d'énumération de type partagé, vous pouvez soit définir l'opérateur == vous-même, soit À moins que le protocole Equtable ne soit adopté, ** ne peut être comparé entre eux **.
python
if turquoise == WebColor.code("#40E0D0") //Erreur. Impossible de comparer
Voici un exemple un peu plus compliqué. Dans l'exemple suivant, nous supposons que l'un des nombreux types de billets et de cartes prépayées vendus dans le métro municipal peut être traité par des portes automatiques, et nous avons défini les types de billets et de cartes comme «type de dénombrement».
python
enum Ticket {
ticket de cas(Int, Bool,Coupon:Bool) //Billet ordinaire: prix, enfant, qu'il s'agisse d'un bon de réduction
carte de cas(Int, Bool) //Carte prépayée: solde, nain
cas Keiro Bus//Bus Keiro
}
Vous pouvez également ajouter des mots-clés aux éléments avec «taple» dans les parenthèses décrites dans le cas. Utilisez «l'instruction switch» pour séparer le traitement d'un tel «type d'énumération». Si vous pouvez attribuer des valeurs aux constantes et aux variables au cas où et ne pas utiliser des «informations supplémentaires», vous pouvez également ne pas écrire ** après les parenthèses ** comme le «.card» ci-dessous **.
Dans ce qui suit, la description de la condition structurelle ** placée après le cas ** est appelée «modèle de cas». De plus, la condition peut être écrite sous où est la même chose que pour "taple". Vérifiez l'exemple suivant.
python
switch t {
case let .billet(fare, flag, _):
print("Billet ordinaire: \(fare) " + (flag ? "enfant" : "adulte"))
case .Bus Keiro:
print("Bus Keiro")
case .carte(let r, true) where r < 110: //Tarif minimum pour les enfants
print("carte:Fonds insuffisants")
case .carte(let r, false) where r < 230: //Tarif minimum pour les adultes
print("carte:Fonds insuffisants")
case .carte:
print("carte")
Similaire à l'utilisation de taple
dans une instruction switch, vous pouvez utiliser let pour être placé à l'intérieur () ou à l'extérieur pour attribuer des informations supplémentaires
à une constante.
python
case let .billet(fare, flag, _): //Ou
case .billet(let fare, let flag, _):
Pour les tuples avec des mots-clés, vous n'avez pas besoin d'écrire une étiquette à l'intérieur du modèle de cas, mais vous le pouvez. Lorsque vous utilisez avec let, vous devez faire attention à l'endroit où vous écrivez let.
python
case let .billet(fare, _,Coupon: flag): //Ou
case .billet(let fare, _,Coupon: let flag):
L'instruction switch était utile pour savoir à laquelle des multiples conditions correspond le taple donné **. Cependant, il peut arriver que vous souhaitiez ** vérifier si une seule condition particulière est remplie **.
Par exemple, supposons que vous souhaitiez simplement savoir si la variable de type de ticket p utilisée dans l'exemple précédent est une carte prépayée. Cependant, l'instruction if ne peut pas être décrite comme suit.
python
if p == .carte{ //Erreur. Cette description n'est pas possible
print("carte prépayée")
}
L'instruction switch peut être écrite comme suit, mais c'est un peu gênant car vous devez écrire la clause par défaut que vous savez que vous n'utiliserez pas.
python
switch p {
case .carte: print("プリペイドcarte")
default: break
}
Par conséquent, il existe une syntaxe qui peut être facilement écrite même dans de tels cas. L'exemple ci-dessus peut être écrit comme suit: Cette syntaxe est parfois appelée «instruction if-case».
python
if case .carte= p {
print("carte prépayée")
Pour la condition, décrivez d'abord le modèle de cas
, puis placez l'expression cible sous la forme" = ".
Le fait que l'expression corresponde au «modèle de cas» est traité de la même manière que dans l'instruction switch.
Contrairement à l'instruction switch, la condition supplémentaire n'est pas une clause where, mais séparée par une virgule "," et suivie.
Cette notation est la même que celle décrite dans Comment écrire des conditions pour les instructions if, while et guard
, et vous pouvez écrire des expressions générales, syntaxe de liaison facultative
, etc., séparées par des virgules.
si motif de cas=formule,conditions{.....}
L'exemple suivant vérifie si le contenu de la variable t est une carte prépayée avec un solde de 1 200 yens ou plus.
python
if case .carte(let y, _) = t, y >= 1200 { .....
Comme exemple un peu plus compliqué, écrivons une condition qui prend un élément de type Ticket à partir d'une instance d'un dictionnaire et vérifie si les informations correspondent au modèle.
python
let tickets:[String:Ticket] = [ "Shikura" : .billet(260, false,Coupon: true),
"Sasaki" : .billet(220, false,Coupon:false)]
let name = "Sasaki"
if let t = tickets[name], case .billet(220, _, _) = t {
print("220 yens billet")
}
Dans le cas de cet exemple, les informations obtenues à partir du dictionnaire sont "type optionnel", donc commencez par obtenir une instance de type Ticket dans la constante t avec "syntaxe de liaison optionnelle". Dans le cas de nul, la condition if n'y est pas satisfaite, mais si elle n'est pas nulle, alors vérifiez si la constante t est un ticket de 220 yens.
L'instruction if ci-dessus peut également être décrite comme suit en utilisant "?".
python
if case .billet(220, _, _)? = tickets[name] {
print("220 yens billet")
}
Vous pouvez également utiliser le modèle de cas
dans l'instruction for-in.
Semblable à l'instruction for-in expliquée jusqu'ici, une expression conforme au "protocole de séquence" telle qu'un tableau est placée à côté de in, et les instances sont récupérées les unes après les autres.
Dans cette écriture, le bloc de code est exécuté uniquement lorsque l'instance récupérée correspond au modèle suivant du cas. Vous pouvez également ajouter une clause where si vous avez besoin d'écrire plus de conditions pour l'exécution.
pour le modèle de cas dans l'expression où expression{
Phrase... ...
}
Par exemple, pour récupérer les instances les unes après les autres à partir du tableau des passes avec des éléments de type Ticket et afficher les informations des tickets supérieurs à 220 yens, procédez comme suit.
python
for case let .billet(fare. child, coupon) in passes where fare > 220 {
var k = coupon ? "Coupon" : "Billet ordinaire"
if child { k += "(enfant)" }
print(k, "\(fare)Cercle")
}
Cette déclaration équivaut à écrire:
python
for t in passes {
switch t {
case let .billet(fare, child, coupon):
if fare > 220 {
var k = coupon ? "Coupon" : "Billet ordinaire"
if child { k += "(enfant)" }
print(k, "\(fare)Cercle")
}
default: break
}
}
Vous pouvez utiliser le "?" Qui s'applique au "type optionnel" dans cette syntaxe pour gérer les chaînes de données contenant le "type optionnel". Vous pouvez également utiliser var au lieu de let.
Vous voudrez peut-être vous spécifier comme un élément à l'intérieur d'un taple avec un type d'énumération partagé
.
Par exemple, considérons le cas suivant.
python
message enum{
document de cas(String, String) //De, document
données de cas(String, [Int8]) //De, colonne de données
transfert de cas(String,message) //De, message
}
Cette déclaration de données ne semble pas être fausse, mais Swift ne peut pas la gérer.
Dans Swift, «type d'énumération» est des données de «type de valeur», donc pour expliquer intuitivement, les informations de chargement sont stockées directement côte à côte dans l'emplacement mémoire qui représente les données de «type d'énumération». Comme mentionné ci-dessus, y compris lui-même, c'est-à-dire que ** les structures de données récursives ne peuvent pas déterminer au moment de la compilation la quantité de mémoire nécessaire pour stocker les données **.
D'autre part, les données de type «référence» sont des informations permettant de référencer indirectement une entité qui existe quelque part dans la mémoire, il n'y a donc pas de problème avec la mémoire.
Cependant, il existe de nombreuses situations où il est utile de pouvoir utiliser le type d'énumération récursive
, donc dans Swift, si le type d'énumération
** s'inclut dans les informations supplémentaires, écrivez le mot-clé indirect avant le cas correspondant. **.
C'est ce qu'on appelle la «spécification indirecte». «Indirect», c'est-à-dire indirect, signifie que seule cette partie est indirectement référencée comme un pointeur.
L'histoire actuelle est illustrée dans l'exemple suivant. Le «protocole CustomStringConvertible» est adopté pour pouvoir être affiché par impression.
python
message enum: CustomStringConvertible {
document de cas(String, String) //De, document
données de cas(String, [Int8]) //De, colonne de données
transfert indirect de cas(String,message) //De, message
ver description: String {
switch self {
case let .documents(from, str): return from + "(" + str + ")"
case let .Les données(from, _): return from + "[Les données]"
case let .transfert(from, msg): return from + "←\(msg)"
}
}
}
Un exemple d'exécution est présenté ci-dessous.
python
let m1 =message.documents("Ito", "Repose toi un peu")
let m2 =message.transfert("Shiraishi", m1)
let m3 =message.transfert("Yamada", m2)
print(m3) // "← Shiraishi ← Ito(Repose toi un peu)"Production
Si vous avez des modèles de cas
récursifs, vous pouvez mettre ʻindirect` devant l'énumération pour faire toute la spécification indirecte.
Cette fois, j'ai écrit un article sur les types d'énumérations partagées, mais je n'expliquerai pas comment gérer les protocoles et les types facultatifs car l'article sera un peu long. À partir de la semaine prochaine, j'expliquerai les cours et ainsi de suite. Merci à tous ceux qui ont lu jusqu'ici.
Recommended Posts