545 Stimmen

Was bedeutet ein Ausrufezeichen in der Swift-Sprache?

Der Leitfaden zur Swift-Programmiersprache hat das folgende Beispiel:

class Person {
    let name: String
    init(name: String) { self.name = name }
    var apartment: Apartment?
    deinit { println("\(name) wird deinitialisiert") }
}

class Apartment {
    let number: Int
    init(number: Int) { self.number = number }
    var tenant: Person?
    deinit { println("Apartment Nr. \(number) wird deinitialisiert") }
}

var john: Person?
var number73: Apartment?

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

// Aus dem Leitfaden "The Swift Programming Language" von Apple (https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/AutomaticReferenceCounting.html)

Dann, wenn das Apartment der Person zugewiesen wird, benutzen sie ein Ausrufezeichen, um die Instanz "auszupacken":

john!.apartment = number73

Was bedeutet es, eine Instanz "auszupacken"? Warum ist es notwendig? Wie unterscheidet es sich davon, einfach folgendes zu tun:

john.apartment = number73

Ich bin ganz neu in der Swift-Sprache. Versuche nur, die Grundlagen zu verstehen.

UPDATE:
Das große Puzzlestück, das mir fehlte (nicht direkt in den Antworten angegeben - zumindest nicht zum Zeitpunkt des Verfassens dieses Beitrags), ist, dass wenn man Folgendes tut:

var john: Person?

das NICHT bedeutet, dass "john vom Typ Person ist und vielleicht nil sein könnte", wie ich ursprünglich dachte. Ich habe einfach missverstanden, dass Person und Person? vollständig separate Typen sind. Sobald ich das verstanden hatte, ergaben alle anderen ?, ! Verwirrungen und die großartigen Antworten unten viel mehr Sinn.

25voto

Fry Punkte 6115

john ist eine optionale var und kann einen nil-Wert enthalten. Um sicherzustellen, dass der Wert nicht nil ist, füge ein ! am Ende des var-Namens hinzu.

Aus der Dokumentation

„Sobald Sie sicher sind, dass die Option ein Wert enthält, können Sie auf ihren zugrunde liegenden Wert zugreifen, indem Sie ein Ausrufezeichen (!) am Ende des Namens der Option hinzufügen. Das Ausrufezeichen sagt im Grunde genommen: „Ich weiß, dass diese Option definitiv einen Wert hat; bitte benutze ihn.““

Ein weiterer Weg, um den nicht-nil-Wert zu überprüfen, ist das optionale Auspacken

    if let j = json {
        // mache etwas mit j
    }

16voto

Ramkumar chintala Punkte 958

Hier sind einige Beispiele:

var name:String = "Hallo Welt"
var word:String?

Wo word einen optionalen Wert darstellt. Das bedeutet, dass es einen Wert enthalten kann oder auch nicht.

word = name 

Hier hat name einen Wert, also können wir ihn zuweisen

var cow:String = nil
var dog:String!

Wo dog erzwungen entpackt wird, das bedeutet, dass es einen Wert enthalten muss

dog = cow

Die Anwendung wird abstürzen, weil wir nil einem entpackten Wert zuweisen

14voto

guest Punkte 161

In diesem Fall...

var John: Person!

das bedeutet, dass John anfangs einen nil-Wert haben wird, der gesetzt wird und dann nie wieder zu nil werden wird. Daher kann ich für Bequemlichkeit die einfachere Syntax zum Zugriff auf eine optionale Variable verwenden, da dies eine "Implicitly unwrapped optional" ist

5voto

Jim Driscoll Punkte 884

Wenn Sie aus einer C-Familiensprache kommen, werden Sie denken "Zeiger auf ein Objekt vom Typ X, das möglicherweise die Speicheradresse 0 (NULL) ist", und wenn Sie aus einer dynamisch typisierten Sprache kommen, werden Sie denken "Objekt, das wahrscheinlich vom Typ X ist, aber möglicherweise vom Typ undefiniert ist". Keines davon ist tatsächlich korrekt, obwohl in gewisser Weise der erste nahe dran ist.

Die Art und Weise, wie Sie darüber nachdenken sollten, ist, als ob es sich um ein Objekt wie:

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

Wenn Sie Ihren optionalen Wert mit foo == nil testen, gibt es eigentlich foo.isNil zurück, und wenn Sie foo! sagen, wird foo.realObject mit der Behauptung zurückgegeben, dass foo.isNil == false. Es ist wichtig zu beachten, dass, denn falls foo tatsächlich nil ist, wenn Sie foo! machen, ist das ein Laufzeitfehler, daher möchten Sie normalerweise lieber ein bedingtes let verwenden, es sei denn Sie sind sehr sicher, dass der Wert nicht nil sein wird. Diese Art von Listigkeit bedeutet, dass die Sprache stark typisiert sein kann, ohne Sie dazu zu zwingen, überall zu prüfen, ob Werte nil sind.

In der Praxis verhält es sich nicht wirklich so, weil die Arbeit vom Compiler erledigt wird. Auf einer hohen Ebene gibt es einen Typ Foo?, der von Foo getrennt ist, und das verhindert, dass Funktionen, die den Typ Foo akzeptieren, einen nil-Wert erhalten, aber auf niedriger Ebene ist ein optionaler Wert kein echtes Objekt, weil er keine Eigenschaften oder Methoden hat; es ist wahrscheinlich, dass es sich tatsächlich um einen Zeiger handelt, der mit dem entsprechenden Test beim Erzwingen des Auspackens NULL(0) sein kann.

Es gibt eine andere Situation, in der Sie ein Ausrufezeichen sehen würden, und zwar bei einem Typ, wie in:

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

Dies entspricht ungefähr dem Akzeptieren eines Optionals mit einer erzwungenen Entfaltung, d.h.:

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

Sie können dies verwenden, um eine Methode zu haben, die technisch einen optionalen Wert akzeptiert, aber einen Laufzeitfehler haben wird, wenn er nil ist. In der aktuellen Version von Swift umgeht dies anscheinend die ist-nicht-nil-Behauptung, sodass Sie stattdessen einen Fehler auf niedriger Ebene haben. Im Allgemeinen keine gute Idee, aber es kann nützlich sein, wenn Sie Code aus einer anderen Sprache konvertieren.

3voto

Abdurrahman Punkte 181

Wenn Sie mit C# vertraut sind, ist dies ähnlich wie Nullable-Typen, die auch mit einem Fragezeichen deklariert werden:

Person? thisPerson;

Und das Ausrufezeichen in diesem Fall entspricht dem Zugriff auf die .Value-Eigenschaft des nullable Typs wie folgt:

thisPerson.Value

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X