Que signifie un point d'exclamation dans le langage Swift?

le guide de langage de programmation Swift a l'exemple suivant:

class Person {
    let name: String
    init(name: String) { self.name = name }
    var apartment: Apartment?
    deinit { println("(name) is being deinitialized") }
}

class Apartment {
    let number: Int
    init(number: Int) { self.number = number }
    var tenant: Person?
    deinit { println("Apartment #(number) is being deinitialized") }
}

var john: Person?
var number73: Apartment?

john = Person(name: "John Appleseed")
number73 = Apartment(number: 73)

//From Apple's “The Swift Programming Language” guide (https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/AutomaticReferenceCounting.html)

ensuite, lors de l'attribution de l'appartement à la personne, ils utilisent un point d'exclamation pour "déballer l'instance":

john!.apartment = number73

Que signifie "ouvrir l'instance"? Pourquoi est-il nécessaire? En quoi est-ce différent de simplement faire ce qui suit:

john.apartment = number73

je suis très nouveau dans le langage Swift. Juste essayer d'obtenir les bases.



mise à jour:

La grande pièce du puzzle que je manquais (pas directement indiqué dans les réponses - au moins pas au moment de la rédaction de ce document) est que lorsque vous faites ce qui suit:

var john: Person?

cela ne signifie pas que john est de type Person et il pourrait être nul", comme je l'ai à l'origine pensée. J'ai simplement compris que Person et Person? sont des types complètement séparés. Une fois que j'ai compris cela, tous les autres ? , ! folie, et les grandes réponses ci-dessous, fait beaucoup plus de sens.

483
demandé sur Cœur 2014-06-03 18:52:26

22 réponses

Que signifie "ouvrir l'instance"? Pourquoi est-il nécessaire?

autant que je puisse le comprendre (c'est très nouveau pour moi aussi)...

le terme "enveloppé" implique que nous devrions penser à une variable optionnelle comme un cadeau, enveloppé dans du papier brillant, qui pourrait (malheureusement!) être vide .

Quand "enveloppé", la valeur d'une variable Optionnelle est un enum avec deux valeurs possibles (un peu comme un Booléen). Cet enum décrit si la variable contient une valeur ( Some(T) ), ou non ( None ).

S'il y a une valeur, On peut l'obtenir en" déballant "la variable (en obtenant le T de Some(T) ).

en quoi john!.apartment = number73 diffère-t-il de john.apartment = number73 ? (Paraphrasé)

Si vous écrivez le nom d'une variable Optionnelle (par exemple texte john , sans le ! ), cela se réfère à l'enum" enveloppé " (certains/Aucun), pas la valeur elle-même (T). Donc john n'est pas un exemple de Person , et il n'a pas de apartment membre:

john.apartment
// 'Person?' does not have a member named 'apartment'

la valeur réelle Person peut être déballée de différentes façons:

  • "déballage forcé": john! (donne la valeur Person si elle existe, erreur d'exécution si elle est nulle)
  • "option obligatoire": if let p = john { println(p) } (exécute le println si la valeur existe)
  • optionnels "chaînage": john?.learnAboutSwift() (exécute cette méthode si la valeur existe)

je suppose que vous choisissez l'une de ces façons de déballer, en fonction de ce qui devrait se passer dans le cas nul, et à quel point c'est probable. Cette conception linguistique oblige le cas nil à être traité explicitement, ce qui, je suppose, améliore la sécurité par rapport à Obj-C (où il est facile d'oublier de traiter le néant cas).

mise à Jour :

le point d'exclamation est également utilisé dans la syntaxe pour déclarer"les options implicitement non emballées".

dans les exemples donnés jusqu'à présent, la variable john a été déclarée comme var john:Person? , et elle est facultative. Si vous voulez la valeur réelle de cette variable, vous devez la déballer, en utilisant l'une des trois méthodes ci-dessus.

si elle était déclarée comme var john:Person! à la place, la variable serait une optionnelle implicitement déballée (voir la section avec cette rubrique dans le livre D'Apple). Il n'est pas nécessaire de déballer ce type de variable lors de l'accès à la valeur, et john peut être utilisé sans syntaxe supplémentaire. Mais le livre D'Apple dit:

implicitement, les options non enveloppées ne doivent pas être utilisées lorsqu'il y a une possibilité qu'une variable devienne nulle à un moment ultérieur. Toujours utiliser un type optionnel normal si vous avez besoin de vérifier une valeur nulle pendant la durée de vie d'une variable.

Update 2 :

L'article " Intéressant Swift Fonctionnalités " par Mike Ash donne de la motivation pour l'option types. Je pense qu'il est grand, clair de l'écriture.

Update 3 :

un autre article utile au sujet du implicitement non enveloppé facultatif utiliser pour le point d'exclamation: " Swift et le dernier mille " par Chris Adamson. L'article explique qu'il s'agit d'une mesure pragmatique d'Apple utilisée pour déclarer les types utilisés par leurs cadres objectifs-C qui pourraient contenir zéro. Déclarer un type comme facultatif (en utilisant ? ) ou implicitement non emballé (en utilisant ! ) est "un compromis entre sécurité et commodité". Dans les exemples donnés dans le article, Apple ont choisi de déclarer les types comme implicitement déballé, ce qui rend le code d'appel plus pratique, mais moins sûr.

peut-être Apple pourrait passer au peigne fin leurs cadres à l'avenir, en supprimant l'incertitude des paramètres implicitement déballés ("probablement jamais nul") et en les remplaçant par optionnel ("certainement pourrait être nul en particulier [avec un peu de chance, documenté!] circonstances") ou déclarations standard non facultatives ("n'est jamais nul"), sur la base comportement de leur code objectif-C.

494
répondu Ashley 2014-07-04 11:28:24

voici ce que je pense être la différence:

var john: Person?

, john peut être nul

john?.apartment = number73

le compilateur interprétera cette ligne comme:

if john != nil {
    john.apartment = number73
}

alors que

john!.apartment = number73

le compilateur interprétera cette ligne comme suit:

john.apartment = number73

donc, en utilisant ! va déballer l'instruction if, et de faire courir plus vite, mais si john est nul, alors une erreur d'exécution arriver.

donc envelopper ici ne signifie pas qu'il est enveloppé de mémoire, mais il signifie qu'il est enveloppé de code, dans ce cas, il est enveloppé avec une déclaration if, et parce que Apple font une attention particulière à la performance en runtime, ils veulent vous donner un moyen de faire fonctionner votre application avec la meilleure performance possible.

mise à jour:

revenir à cette réponse après 4 ans, car j'ai obtenu les plus hautes réputations de celui-ci en Stackoverflow :) J'ai un peu mal compris le sens du déballage à ce moment-là. Maintenant, après 4 ans, je crois, le sens de déballer ici est d'étendre le code de sa forme compacte. Cela signifie également supprimer le flou autour de cet objet, car nous ne sommes pas sûrs par définition de lui est nul ou non. Tout comme la réponse D'Ashley ci-dessus, pensez-y comme un cadeau qui ne pourrait rien contenir. Mais je pense toujours que le déballage est déballage de code et pas de mémoire basée déballage comme en utilisant l'enum.

119
répondu Amr 2018-01-11 20:01:28

TL; DR

que signifie un point d'exclamation dans le langage Swift?

le point d'exclamation dit effectivement, " je sais que cette option a certainement une valeur; s'il vous plaît l'utiliser."Ceci est connu sous le nom de déballage forcé de la valeur de l'option:

exemple

let possibleString: String? = "An optional string."
print(possibleString!) // requires an exclamation mark to access its value
// prints "An optional string."

let assumedString: String! = "An implicitly unwrapped optional string."
print(assumedString)  // no exclamation mark is needed to access its value
// prints "An implicitly unwrapped optional string."

Source: https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/TheBasics.html#//apple_ref/doc/uid/TP40014097-CH5-XID_399

62
répondu Alex Nolasco 2017-06-29 16:36:15

si Jean était un var optionnel (déclaré thusly)

var john: Person?

alors il serait possible pour Jean d'avoir aucune valeur (en langage ObjC, valeur nulle)

le point d'exclamation dit essentiellement au compilateur"je sais que cela a une valeur, vous n'avez pas besoin de le tester". Si vous ne voulez pas l'utiliser, vous pouvez le tester sous condition:

if let otherPerson = john {
    otherPerson.apartment = number73
}

l'intérieur de ceci évaluera seulement si john a une valeur.

37
répondu Ben Gottlieb 2014-06-03 15:06:11

Certains point de vue global à ajouter à l'autre utile, mais plus en détail centrée sur les réponses:

dans Swift, le point d'exclamation apparaît dans plusieurs contextes:

  • déballage forcé: let name = nameLabel!.text
  • options implicitement non emballées: var logo: UIImageView!
  • moulage forcé: logo.image = thing as! UIImage
  • exceptions sans limitation: try! NSJSONSerialization.JSONObjectWithData(data, [])

chacun d'eux est une construction de langue différente avec un sens différent, mais ils ont tous trois choses importantes en commun:

1. Les points d'Exclamation contournent les contrôles de sécurité de la compilation de Swift.

quand vous utilisez ! dans Swift, vous dites essentiellement," Hé, compilateur, je sais que vous pensez qu'une erreur pourrait se produire ici, mais je savoir avec une certitude totale qu'il n'a jamais sera."

tous les codes valides ne correspondent pas à la case du système de type de compilation de Swift-ou n'importe quel vérification de type statique de la langue, d'ailleurs. Il y a des situations où vous pouvez logiquement prouver qu'une erreur n'arrivera jamais, mais vous ne pouvez pas le prouver au compilateur . C'est pourquoi les concepteurs de Swift ont d'abord ajouté ces fonctionnalités.

Cependant, chaque fois que vous utilisez ! , vous êtes décision à un chemin de récupération pour une erreur, ce qui signifie que...

2. Les points d'Exclamation sont des crashs potentiels.

un point d'exclamation dit aussi, "Hey Swift, je suis donc certain que cette erreur ne peut jamais se produire qu'il est mieux pour vous de planter toute mon application que ce qu'il est pour moi de coder un chemin de récupération pour elle."

c'est une affirmation dangereuse. Il peut soit le bon: dans le code critique de la mission où vous avez beaucoup réfléchi sur les invariants de votre code, il se peut que la sortie bidon soit pire qu'un crash.

cependant, quand je vois ! dans la nature, il est rarement utilisé aussi consciencieusement. Au lieu de cela, cela signifie Trop souvent, "cette valeur était facultative et je n'ai pas vraiment pensé trop dur à pourquoi il pourrait être nul ou comment gérer correctement cette situation, mais en ajoutant ! fait compiler ... donc mon code est correct, non?"

méfiez-vous de l'arrogance du point d'exclamation. Au lieu de cela ...

3. Les points d'Exclamation sont mieux utilisés avec parcimonie.

chacune de ces constructions ! a une contrepartie ? qui vous oblige à traiter le cas erreur/néant:

  • déballage conditionnel: if let name = nameLabel?.text { ... }
  • options: var logo: UIImageView?
  • casts conditionnels: logo.image = thing as? UIImage
  • Néant-sur-l'échec des exceptions: try? NSJSONSerialization.JSONObjectWithData(data, [])

si vous êtes tenté d'utiliser ! , il est toujours bon de bien réfléchir pourquoi vous n'utilisez pas ? à la place. Est-ce que planter votre programme est vraiment la meilleure option si l'opération ! échoue? pourquoi cette valeur est-elle optionnelle/non fiable?

est - il un chemin de récupération raisonnable que votre code pourrait prendre dans le cas d'un zéro / erreur? Si oui, code.

si cela ne peut pas être nul, si l'erreur ne peut jamais se produire, alors y a-t-il un moyen raisonnable de retravailler votre logique pour que le compilateur le sache? Si c'est le cas, faites-le; votre code sera moins sujet aux erreurs.

il y a des moments où il n'y a pas de façon raisonnable de traiter une erreur, et simplement ignorer l'erreur - et donc procéder avec des données erronées - serait pire que s'écraser. ces sont les moments où il faut recourir à la force pour déballer.

je fais périodiquement des recherches dans ma base de données complète pour trouver ! et je vérifie chaque utilisation de celui-ci. Très peu d'usages résistent à l'examen. (Au moment de la rédaction de cet article, le cadre Siesta complet a exactement deux 15191000920 "instances de celui-ci.)

cela ne veut pas dire que vous devriez jamais utiliser ! dans votre code - juste que vous devriez l'utiliser mindfully , et ne jamais en faire l'option par défaut.

25
répondu Paul Cantrell 2018-03-20 22:20:56

john est une option var . Peut donc contenir une valeur nil . Pour vous assurer que la valeur n'est pas nulle, utilisez un ! à la fin du nom var .

à Partir de la documentation

" une fois que vous êtes sûr que l'option contient une valeur, vous pouvez accéder à sa valeur sous-jacente en ajoutant un point d'exclamation (! à la fin de l'option du même nom. Le point d'exclamation dit effectivement, "je sais que cette option a certainement une valeur; merci de l'utiliser."

une autre façon de vérifier la valeur non nulle est

    if let j = json {
        // do something with j
    }
24
répondu Fry 2017-01-19 15:30:21

voici quelques exemples:

var name:String = "Hello World"
var word:String?

word est une valeur facultative. signifie qu'il peut contenir ou non une valeur.

word = name 

ici name a une valeur donc nous pouvons l'attribuer

var cow:String = nil
var dog:String!

dog est fortement déballé signifie qu'il doit contenir une valeur

dog = cow

l'application s'écrasera parce que nous assignons nil à unwrapped

16
répondu Ramkumar chintala 2017-08-01 07:25:53

dans ce cas...

var John: personne!

cela signifie qu'initialement Jean aura une valeur nulle, elle sera fixée et une fois fixée ne sera plus jamais dirigée nulle. Par conséquent, pour des raisons de commodité, je peux utiliser la syntaxe la plus simple pour accéder à un var optionnel, car il s'agit d'un "optionnel implicitement déballé"

13
répondu guest 2014-07-24 21:50:01

si vous venez d'un langage C-family, vous penserez" pointeur vers objet de type X qui pourrait être l'adresse mémoire 0 (NULL)", et si vous venez d'un langage dynamiquement tapé vous penserez"objet qui est probablement de type X mais pourrait être de type non défini". Ni l'un ni l'autre n'est en fait correct, bien que de manière détournée le premier soit proche.

la façon dont vous devriez y penser est comme si c'était un objet comme:

struct Optional<T> {
   var isNil:Boolean
   var realObject:T
}

quand vous testez votre valeur optionnelle avec foo == nil c'est vraiment retourner foo.isNil , et quand vous dites foo! c'est retourner foo.realObject avec une assertion que foo.isNil == false . Il est important de noter ceci parce que si foo est en fait nul lorsque vous faites foo! , c'est une erreur d'exécution, donc typiquement vous voulez utiliser un let conditionnel à la place sauf si vous êtes très sûr que la valeur ne sera pas nulle. Ce genre de supercherie signifie que l' la langue peut être fortement tapée sans vous forcer à tester si les valeurs sont nulles partout.

dans la pratique, il ne se comporte pas vraiment comme cela parce que le travail est fait par le compilateur. A un niveau élevé il y a un type Foo? qui est séparé de Foo , et qui empêche les fonctions qui acceptent le type Foo de recevoir une valeur nulle, mais à un niveau bas une valeur optionnelle n'est pas un objet vrai parce qu'il n'a pas de propriétés ou de méthodes; il est probable qu'en fait c'est un pointeur qui peut être nul(0) avec le test approprié lors du déballage par force.

il y a une autre situation dans laquelle vous verriez un point d'exclamation est sur un type, comme dans:

func foo(bar: String!) {
    print(bar)
}

cela revient à peu près à accepter une option avec un déballage forcé, c'est-à-dire:

func foo(bar: String?) {
    print(bar!)
}

vous pouvez utiliser ceci pour avoir une méthode qui accepte techniquement une valeur optionnelle mais aura une erreur d'exécution si elle est nulle. Dans le version actuelle de Swift ceci contourne apparemment l'assertion is-not-nil de sorte que vous aurez une erreur de bas niveau à la place. Généralement pas une bonne idée, mais il peut être utile lors de la conversion de code d'une autre langue.

4
répondu Jim Driscoll 2016-02-19 10:52:24

The ! cela signifie que vous êtes la force de déballer l'objet le ! suivre. Plus d'informations peuvent être trouvées dans la documentation de pommes, qui peut être trouvé ici: https://developer.apple.com/library/ios/documentation/swift/conceptual/Swift_Programming_Language/TheBasics.html

3
répondu Henry oscannlain-miller 2014-11-16 02:30:05

si vous êtes familier avec C#, c'est comme les types annulables qui sont également déclarés en utilisant un point d'interrogation:

Person? thisPerson;

et le point d'exclamation dans ce cas est équivalent à accéder au .Propriété de valeur du type nullable comme ceci:

thisPerson.Value
3
répondu Abdurrahman 2015-10-20 14:23:42

dans l'objectif C, Les variables sans valeur étaient égales à "zéro" (il était également possible d'utiliser des valeurs " nul "identiques à 0 et à false), de sorte qu'il était possible d'utiliser des variables dans des énoncés conditionnels (les Variables ayant des valeurs étaient identiques à "vrai" et celles sans valeur étaient égales à "FALSE").

Swift fournit une sécurité de type en fournissant une "valeur optionnelle". c'est-à-dire qu'il empêche les erreurs formées d'assigner des variables de différents types.

Donc en Swift, seuls les booléens peuvent être fournis sur des déclarations conditionnelles.

var hw = "Hello World"

ici, même si 'hw' est une chaîne de caractères, elle ne peut pas être utilisée dans une instruction if comme dans l'objectif C.

//This is an error

if hw

 {..}

Pour cela il doit être créé comme,

var nhw : String? = "Hello World"

//This is correct

if nhw

 {..}
2
répondu Gokul 2014-06-26 17:56:36

The ! à la fin d'un objet dit que l'objet est une option et de déballer si il peut sinon, retourne zéro. Ceci est souvent utilisé pour piéger les erreurs qui, autrement, écraseraient le programme.

2
répondu cheborneck 2015-06-09 06:09:20

En Bref (!): Après avoir déclaré une variable et que vous êtes certain que la variable détient une valeur.

let assumedString: String! = "Some message..."
let implicitString: String = assumedString

sinon vous auriez à faire cela sur chaque valeur après passage...

let possibleString: String? = "An optional string."
let forcedString: String = possibleString! // requires an exclamation mark
2
répondu En Hui Lim 2016-01-07 07:53:49

Jean est une personne facultative, ce qui signifie qu'elle peut détenir une valeur OU être nulle.

john.apartment = number73

est utilisé si Jean n'est pas facultatif. Puisque john n'est jamais nul, nous pouvons être sûrs qu'il ne sera pas appelé appartement sur une valeur nulle. Tandis que

john!.apartment = number73

promet au compilateur que Jean n'est pas nul puis déballe l'option pour obtenir la valeur de Jean et accède à la propriété de l'appartement de Jean. Utilisez ceci si vous savez que Jean n'est pas nul. Si vous appelez cela sur un zéro optionnel, vous obtiendrez une erreur d'exécution.

la documentation inclut un bel exemple pour l'utilisation de ce où convertedNumber est une option.

if convertedNumber {
    println("\(possibleNumber) has an integer value of \(convertedNumber!)")
} else {
    println("\(possibleNumber) could not be converted to an integer")
}
1
répondu Connor 2014-06-03 15:12:04

pour le dire simplement, les points d'exclamation signifient qu'une option est déballée. Une option est une variable qui peut avoir une valeur ou pas -- ainsi vous pouvez vérifier si la variable est vide, en utilisant un if let instruction comme montré ici , et puis forcer unwrap it. Si vous forcez un unwrap optionnel qui est vide cependant, votre programme va se planter, alors faites attention! Options sont déclarées en mettant un point d'interrogation à la fin d'une affectation explicite à une variable, par exemple je pourrais écrire:

var optionalExample: String?

cette variable n'a pas de valeur. Si j'étais à déballer, le programme plante et Xcode vous dire vous avez essayé de déballer une option avec une valeur de néant.

Espère que cela a aidé.

1
répondu brimstone 2015-02-26 18:25:25

EN TERMES SIMPLES

L'utilisation D'un point d'Exclamation indique que la variable doit se composer d'une valeur non nulle (elle ne sera jamais nulle)

1
répondu Maninderjit Singh 2016-05-23 13:03:00

toute l'histoire commence par une caractéristique de swift appelée vor optionnel. Ce sont les revendeurs qui peuvent avoir une valeur ou ne peuvent pas avoir de valeur. En général, swift ne nous permet pas d'utiliser une variable qui n'est pas initialisée, car cela peut conduire à des crashs ou des raisons inattendues, et aussi à un serveur de stockage pour les portes dérobées. Ainsi, pour déclarer une variable dont la valeur n'est pas initialement déterminée, nous utilisons a '?'. Lorsqu'une variable est déclarée, à l'utiliser comme une partie d'une expression qu'on a à les déballer avant utilisation, déballer est une opération par laquelle la valeur d'une variable est découverte.ceci s'applique aux objets. Sans ôter si vous essayez de les utiliser, vous aurez erreur de compilation. Pour déballer une variable qui est un var optionnel, point d'exclamation "!"est utilisé.

maintenant , il y a des moments où vous savez que de telles variables optionnelles se verront attribuer des valeurs par le système, par exemple, ou par votre propre programme, mais plus tard, par exemple, les points de vente de L'assurance-chômage, dans une telle situation. au lieu de déclarer une variable optionnelle en utilisant un point d'interrogation "?"nous "!".

Ainsi le système sait que cette variable qui est déclarée avec "!"est optionnel dès maintenant et n'a aucune valeur mais recevra une valeur plus tard dans sa vie.

ainsi le point d'exclamation tient deux usages différents, 1. Pour déclarer une variable qui sera optionnelle et recevra la valeur définitivement plus tard 2. Déballer une variable optionnelle avant de l'utiliser dans une expression.

ci-dessus les descriptions évitent trop de choses techniques, je l'espère.

1
répondu vishal dharankar 2017-01-19 11:02:42

si vous l'utilisez comme un optionnel, il déballe l'optionnel et voit si quelque chose est là. Si vous l'utilisez dans un if-else est est le code pour PAS. Par exemple,

if (myNumber != 3){
 // if myNumber is NOT 3 do whatever is inside these brackets.
)
1
répondu Andy Lebowitz 2017-08-14 03:13:12

une variable facultative peut contenir une valeur ou ne pas être

cas 1: var myVar:String? = "Something"

cas 2: var myVar:String? = nil

maintenant si vous demandez à myVar!, vous dites compilateur pour retourner une valeur dans le cas 1 il retournera "Something"

dans le cas 2, il va s'écraser.

ce qui veut dire ! mark va forcer compilateur à retourner une valeur, même si elle n'est pas là. c'est pourquoi le nom Force Déballage .

1
répondu Ashish Pisey 2017-09-18 04:29:03
Simple the Optional variable allows nil to be stored.

var str : String? = nil

str = "Data"

To convert Optional to the Specific DataType, We unwrap the variable using the keyword "!"

func get(message : String){
   return
}

get(message : str!)  // Unwapped to pass as String
0
répondu jeff ayan 2017-09-19 08:01:03

DEMANDEZ-VOUS

  • le type person? avoir une apartment membre de la propriété? Ou
  • est-ce que le type person a un apartment membre/propriété?

si vous ne pouvez pas répondre à cette question, Alors continuez à lire:

pour comprendre que vous pouvez avoir besoin super-niveau de compréhension de base de génériques . Voir ici . Beaucoup de choses dans Swift sont écrites en utilisant des génériques. Options included

le code ci-dessous est disponible à partir de cette vidéo de Stanford . Je vous recommande vivement de regarder les 5 premières minutes

une option est un enum avec seulement 2 cas

enum Optional<T>{
    case None
    case Some(T)
}

let x: String? = nil //actually means:

let x = Optional<String>.None

let x :String? = "hello" //actually means:

let x = Optional<String>.Some("hello")

var y = x! // actually means:

switch x {
case .Some(let value): y = value
case .None: // Raise an exception
}

reliure facultative:

let x:String? = something
if let y = x {
    // do something with y
}
//Actually means:

switch x{
case .Some(let y): print)(y) // or whatever else you like using 
case .None: break
}

quand vous dites var john: Person? vous voulez dire tel:

enum Optional<Person>{
case .None
case .Some(Person)
}

le ci-dessus enum ont tout propriété nommé apartment ? Tu le vois quelque part? C'est pas là-bas du tout! Cependant, si vous le déballez c'est à dire faire person! alors vous pouvez ... ce qu'il fait sous le capot : Optional<Person>.Some(Person(name: "John Appleseed"))


si vous aviez défini var john: Person au lieu de: var john: Person? alors vous n'auriez plus eu besoin d'avoir le ! utilisé, parce que Person lui-même a un membre de apartment


comme une discussion future sur la raison pour laquelle l'utilisation de ! pour déballer est parfois déconseillée voir cette Q&R

-1
répondu Honey 2017-10-12 18:45:40