Swift - Kurzanleitung

Swift 4 ist eine neue Programmiersprache, die von Apple Inc für die Entwicklung von iOS und OS X entwickelt wurde. Swift 4 übernimmt das Beste aus C und Objective-C ohne die Einschränkungen der C-Kompatibilität.

  • Swift 4 verwendet sichere Programmiermuster.

  • Swift 4 bietet moderne Programmierfunktionen.

  • Swift 4 bietet eine Objective-C-ähnliche Syntax.

  • Swift 4 ist eine fantastische Möglichkeit, iOS- und OS X-Apps zu schreiben.

  • Swift 4 bietet nahtlosen Zugriff auf vorhandene Cocoa-Frameworks.

  • Swift 4 vereint die prozeduralen und objektorientierten Teile der Sprache.

  • Swift 4 benötigt keinen separaten Bibliotheksimport, um Funktionen wie Eingabe / Ausgabe oder Zeichenfolgenbehandlung zu unterstützen.

Swift 4 verwendet dieselbe Laufzeit wie das vorhandene Obj-C-System unter Mac OS und iOS, wodurch Swift 4-Programme auf vielen vorhandenen iOS 6- und OS X 10.8-Plattformen ausgeführt werden können.

Swift 4 verfügt über eine Spielplatzfunktion, mit der Swift 4-Programmierer ihren Code schreiben und ausführen können, um die Ergebnisse sofort anzuzeigen.

Die erste öffentliche Veröffentlichung von Swift wurde im Jahr 2010 veröffentlicht. Es dauerte Chris LattnerFast 14 Jahre, um die erste offizielle Version zu entwickeln, und später wurde sie von vielen anderen Mitwirkenden unterstützt. Swift 4 wurde in die Xcode 6 Beta aufgenommen.

Schnelle Designer nahmen Ideen aus verschiedenen anderen populären Sprachen wie Objective-C, Rust, Haskell, Ruby, Python, C # und CLU auf.

Einrichtung der lokalen Umgebung

Swift 4 bietet eine Spielplatzplattform für Lernzwecke und wir werden dieselbe einrichten. Sie benötigen die xCode-Software, um Ihre Swift 4-Codierung in Playground zu starten. Sobald Sie mit den Konzepten von Swift 4 vertraut sind, können Sie xCode IDE für die Entwicklung von iOS / OS x-Anwendungen verwenden.

Wir gehen davon aus, dass Sie bereits ein Konto auf der Apple Developer-Website haben. Sobald Sie angemeldet sind, gehen Sie zum folgenden Link - Download für Apple-Entwickler

Dadurch wird eine Reihe von Software aufgelistet, die wie folgt verfügbar ist:

Wählen Sie nun xCode aus und laden Sie es herunter, indem Sie auf den angegebenen Link neben dem Disc-Image klicken. Nachdem Sie die dmg-Datei heruntergeladen haben, können Sie sie installieren, indem Sie einfach darauf doppelklicken und den angegebenen Anweisungen folgen. Befolgen Sie abschließend die angegebenen Anweisungen und legen Sie das xCode-Symbol im Anwendungsordner ab.

Jetzt haben Sie xCode auf Ihrem Computer installiert. Öffnen Sie anschließend Xcode aus dem Anwendungsordner und fahren Sie fort, nachdem Sie die allgemeinen Geschäftsbedingungen akzeptiert haben. Wenn alles in Ordnung ist, wird der folgende Bildschirm angezeigt:

Wählen Get started with a playgroundOption und geben Sie einen Namen für den Spielplatz ein und wählen Sie iOS als Plattform. Schließlich erhalten Sie das Spielplatzfenster wie folgt:

Es folgt der Code aus dem Standardfenster von Swift 4 Playground.

import UIKit
var str = "Hello, playground"

Wenn Sie dasselbe Programm für das OS X-Programm erstellen, enthält es den Import von Kakao und das Programm sieht wie folgt aus:

import Cocoa
var str = "Hello, playground"

Wenn das obige Programm geladen wird, sollte das folgende Ergebnis im Ergebnisbereich des Spielplatzes (rechte Seite) angezeigt werden.

Hello, playground

Herzlichen Glückwunsch, Sie haben Ihre Swift 4-Programmierumgebung bereit und können mit Ihrem Lernfahrzeug "Tutorials Point" fortfahren.

Wir haben bereits ein Teil des Swift 4-Programms beim Einrichten der Umgebung gesehen. Beginnen wir noch einmal mit dem FolgendenHello, World! Programm für OS X Spielplatz erstellt, die enthält import Cocoa wie unten gezeigt -

/* My first program in Swift 4 */
var myString = "Hello, World!"

print(myString)

Wenn Sie dasselbe Programm für den iOS-Spielplatz erstellen, wird es enthalten import UIKit und das Programm sieht wie folgt aus:

import UIKit
var myString = "Hello, World!"
print(myString)

Wenn wir das obige Programm auf einem geeigneten Spielplatz ausführen, erhalten wir das folgende Ergebnis:

Hello, World!

Lassen Sie uns nun die Grundstruktur eines Swift 4-Programms sehen, damit Sie die Grundbausteine ​​der Programmiersprache Swift 4 leicht verstehen können.

Import in Swift 4

Du kannst den ... benutzen importAnweisung zum Importieren eines Objective-C-Frameworks (oder einer C-Bibliothek) direkt in Ihr Swift 4-Programm. Zum Beispiel die oben genanntenimport cocoa Die Anweisung stellt alle Cocoa-Bibliotheken, APIs und Laufzeiten, die die Entwicklungsschicht für OS X bilden, in Swift 4 zur Verfügung.

Cocoa ist in Objective-C implementiert, einer Obermenge von C, sodass es einfach ist, C und sogar C ++ in Ihre Swift 4-Anwendungen zu mischen.

Token in Swift 4

Ein Swift 4-Programm besteht aus verschiedenen Token, und ein Token ist entweder ein Schlüsselwort, ein Bezeichner, eine Konstante, ein Zeichenfolgenliteral oder ein Symbol. Die folgende Swift 4-Anweisung besteht beispielsweise aus drei Token:

print("test!")
The individual tokens are:
print("test!")

Bemerkungen

Kommentare sind wie Hilfetexte in Ihrem Swift 4-Programm. Sie werden vom Compiler ignoriert. Mehrzeilige Kommentare beginnen mit / * und enden mit den Zeichen * / wie unten gezeigt -

/* My first program in Swift 4 */

Mehrzeilige Kommentare können in Swift 4 verschachtelt werden. Es folgt ein gültiger Kommentar in Swift 4 -

/* My first program in Swift 4 is Hello, World!
/* Where as second program is Hello, Swift 4! */ */

Einzeilige Kommentare werden mit // am Anfang des Kommentars geschrieben.

// My first program in Swift 4

Semikolons

Bei Swift 4 müssen Sie nach jeder Anweisung in Ihrem Code kein Semikolon (;) eingeben, obwohl dies optional ist. und wenn Sie ein Semikolon verwenden, beschwert sich der Compiler nicht darüber.

Wenn Sie jedoch mehrere Anweisungen in derselben Zeile verwenden, muss ein Semikolon als Trennzeichen verwendet werden, da sonst der Compiler einen Syntaxfehler auslöst. Sie können das obige Hallo, Welt schreiben! Programm wie folgt -

/* My first program in Swift 4 */
var myString = "Hello, World!"; print(myString)

Kennungen

Ein Swift 4-Bezeichner ist ein Name, mit dem eine Variable, eine Funktion oder ein anderes benutzerdefiniertes Element identifiziert wird. Ein Bezeichner beginnt mit einem Alphabet von A bis Z oder von A bis Z oder einem Unterstrich _, gefolgt von null oder mehr Buchstaben, Unterstrichen und Ziffern (0 bis 9).

Swift 4 erlaubt keine Sonderzeichen wie @, $ und% in Bezeichnern. Swift 4 ist eincase sensitiveProgrammiersprache. Daher sind Manpower und Manpower in Swift 4 zwei verschiedene Bezeichner. Hier einige Beispiele für akzeptable Bezeichner:

Azad        zara   abc   move_name   a_123
myname50    _temp  j     a23b9       retVal

Um ein reserviertes Wort als Kennung zu verwenden, müssen Sie davor und danach ein Backtick (`) setzen. Zum Beispiel,class ist keine gültige Kennung, sondern `class`ist gültig.

Schlüsselwörter

Die folgenden Schlüsselwörter sind in Swift 4 reserviert. Diese reservierten Wörter dürfen nicht als Konstanten oder Variablen oder andere Bezeichnernamen verwendet werden, es sei denn, sie werden mit Backticks maskiert.

In Deklarationen verwendete Schlüsselwörter

Klasse deinit Aufzählung Erweiterung
Func importieren Drin intern
Lassen Operator Privat Protokoll
Öffentlichkeit statisch struct Index
Typealien var

In Anweisungen verwendete Schlüsselwörter

Unterbrechung Fall fortsetzen Standard
tun sonst durchfallen zum
wenn im Rückkehr Schalter
wo während

In Ausdrücken und Typen verwendete Schlüsselwörter

wie dynamicType falsch ist
Null selbst Selbst Super
wahr _SÄULE_ _DATEI_ _FUNKTION_
_LINIE_

In bestimmten Kontexten verwendete Schlüsselwörter

Assoziativität Bequemlichkeit dynamisch didSet
Finale bekommen Infix inout
faul links mutieren keiner
nicht mutierend Optional überschreiben Postfix
Vorrang Präfix Protokoll erforderlich
Recht einstellen Art nicht besessen
schwach willSet

Leerzeichen

Eine Zeile, die nur Leerzeichen enthält, möglicherweise mit einem Kommentar, wird als Leerzeile bezeichnet, und ein Swift 4-Compiler ignoriert sie vollständig.

Whitespace ist der Begriff, der in Swift 4 verwendet wird, um Leerzeichen, Tabulatoren, Zeilenumbrüche und Kommentare zu beschreiben. Leerzeichen trennen einen Teil einer Anweisung von einem anderen und ermöglichen dem Compiler zu identifizieren, wo ein Element in einer Anweisung, wie z. B. int, endet und das nächste Element beginnt. Daher in der folgenden Aussage -

var age

Es muss mindestens ein Leerzeichen (normalerweise ein Leerzeichen) dazwischen sein var und agedamit der Compiler sie unterscheiden kann. Auf der anderen Seite in der folgenden Aussage -

int fruit = apples + oranges   //get the total fruits

Zwischen Obst und = oder zwischen = und Äpfeln sind keine Leerzeichen erforderlich, obwohl Sie einige zur besseren Lesbarkeit einfügen können.

Der Abstand auf beiden Seiten eines Bedieners sollte gleich sein, z.

int fruit = apples +oranges    //is a wrong statement
int fruit = apples + oranges   //is a Correct statement

Literale

Ein Literal ist die Quellcodedarstellung eines Werts einer Ganzzahl, einer Gleitkommazahl oder eines Zeichenfolgentyps. Das Folgende sind Beispiele für Literale -

92               // Integer literal
4.24159          // Floating-point literal
"Hello, World!"  // String literal

Drucken in Swift

Um alles schnell zu drucken, haben wir das Schlüsselwort 'print'.

Druck hat drei verschiedene Eigenschaften.

Items - Zu druckende Artikel

Separator - Trennzeichen zwischen Elementen

Terminator - Der Wert, mit dem die Zeile enden soll. Sehen wir uns ein Beispiel und eine Syntax dafür an.

print("Items to print", separator: "Value " , terminator: "Value")
// E.g. of print statement.

print("Value one")
// prints "Value one \n" Adds, \n as terminator and " " as separator by
default.

print("Value one","Value two", separator: " Next Value" , terminator: " End")
//prints "Value one Next Value Value two End"

Im obigen Code fügt die erste Druckanweisung standardmäßig \ n, Zeilenumbruch als Terminator hinzu, wobei wir wie in der zweiten Druckanweisung "Ende" als Terminator angegeben haben, daher wird "Ende" anstelle von \ n gedruckt.

Wir können unsere kundenspezifischen Trennzeichen und Terminatoren gemäß unseren Anforderungen geben.

Während Sie in einer beliebigen Programmiersprache programmieren, müssen Sie verschiedene Arten von Variablen zum Speichern von Informationen verwenden. Variablen sind nichts anderes als reservierte Speicherplätze zum Speichern von Werten. Dies bedeutet, dass Sie beim Erstellen einer Variablen Speicherplatz im Speicher reservieren.

Möglicherweise möchten Sie Informationen verschiedener Datentypen wie Zeichenfolge, Zeichen, breites Zeichen, Ganzzahl, Gleitkomma, Boolescher Wert usw. speichern. Basierend auf dem Datentyp einer Variablen weist das Betriebssystem Speicher zu und entscheidet, was im reservierten Bereich gespeichert werden kann Erinnerung.

Integrierte Datentypen

Swift 4 bietet dem Programmierer eine große Auswahl an integrierten und benutzerdefinierten Datentypen. Die folgenden Arten von Basisdatentypen treten am häufigsten bei der Deklaration von Variablen auf:

  • Int or UInt- Dies wird für ganze Zahlen verwendet. Insbesondere können Sie Int32, Int64 verwenden, um eine vorzeichenbehaftete 32- oder 64-Bit-Ganzzahl zu definieren, während UInt32 oder UInt64, um vorzeichenlose 32- oder 64-Bit-Ganzzahlvariablen zu definieren. Zum Beispiel 42 und -23.

  • Float- Dies wird verwendet, um eine 32-Bit-Gleitkommazahl und Zahlen mit kleineren Dezimalstellen darzustellen. Zum Beispiel 3.14159, 0.1 und -273.158.

  • Double- Dies wird verwendet, um eine 64-Bit-Gleitkommazahl darzustellen, und wird verwendet, wenn Gleitkommawerte sehr groß sein müssen. Zum Beispiel 3.14159, 0.1 und -273.158.

  • Bool - Dies stellt einen booleschen Wert dar, der entweder wahr oder falsch ist.

  • String- Dies ist eine geordnete Sammlung von Zeichen. Zum Beispiel "Hallo Welt!"

  • Character- Dies ist ein einstelliges Zeichenfolgenliteral. Zum Beispiel "C"

  • Optional - Dies stellt eine Variable dar, die entweder einen Wert oder keinen Wert enthalten kann.

  • Tuples - Dies wird verwendet, um mehrere Werte in einem einzigen zusammengesetzten Wert zu gruppieren.

Wir haben hier einige wichtige Punkte im Zusammenhang mit Integer-Typen aufgelistet -

  • Auf einer 32-Bit-Plattform hat Int dieselbe Größe wie Int32.

  • Auf einer 64-Bit-Plattform hat Int dieselbe Größe wie Int64.

  • Auf einer 32-Bit-Plattform hat UInt dieselbe Größe wie UInt32.

  • Auf einer 64-Bit-Plattform hat UInt dieselbe Größe wie UInt64.

  • Int8, Int16, Int32, Int64 können verwendet werden, um 8-Bit-, 16-Bit-, 32-Bit- und 64-Bit-Formen von Ganzzahlen mit Vorzeichen darzustellen.

  • UInt8, UInt16, UInt32 und UInt64 können verwendet werden, um 8-Bit-, 16-Bit-, 32-Bit- und 64-Bit-Formen von Ganzzahlen ohne Vorzeichen darzustellen.

Gebundene Werte

Die folgende Tabelle zeigt den Variablentyp, wie viel Speicher zum Speichern des Werts im Speicher erforderlich ist und welchen Maximal- und Minimalwert in einem solchen Variablentyp gespeichert werden kann.

Art Typische Bitbreite Typischer Bereich
Int8 1 Byte -127 bis 127
UInt8 1 Byte 0 bis 255
Int32 4 Bytes -2147483648 bis 2147483647
UInt32 4 Bytes 0 bis 4294967295
Int64 8 Bytes -9223372036854775808 bis 9223372036854775807
UInt64 8 Bytes 0 bis 18446744073709551615
Schweben 4 Bytes 1,2E-38 bis 3,4E + 38 (~ 6 Stellen)
Doppelt 8 Bytes 2,3E-308 bis 1,7E + 308 (~ 15 Stellen)

Geben Sie Aliase ein

Sie können mit einen neuen Namen für einen vorhandenen Typ erstellen typealias. Hier ist die einfache Syntax zum Definieren eines neuen Typs mithilfe von Typealias:

typealias newname = type

Beispielsweise weist die folgende Zeile den Compiler an, dies zu tun Feet ist ein anderer Name für Int - -

typealias Feet = Int

Die folgende Deklaration ist nun völlig legal und erstellt eine ganzzahlige Variable namens distance -.

typealias Feet = Int
var distance: Feet = 100
print(distance)

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis.

100

Typ Sicherheit

Swift 4 ist eine typsichere Sprache. Wenn ein Teil Ihres Codes einen String erwartet, können Sie ihm nicht versehentlich ein Int übergeben.

Da Swift 4 typsicher ist, führt es beim Kompilieren Ihres Codes Typprüfungen durch und kennzeichnet nicht übereinstimmende Typen als Fehler.

var varA = 42
varA = "This is hello"
print(varA)

Wenn wir das obige Programm kompilieren, erzeugt es den folgenden Fehler bei der Kompilierung.

main.swift:2:8: error: cannot assign value of type 'String' to type 'Int'
varA = "This is hello"

Typ Inferenz

Die Typinferenz ermöglicht es einem Compiler, den Typ eines bestimmten Ausdrucks beim Kompilieren Ihres Codes automatisch abzuleiten, indem er einfach die von Ihnen angegebenen Werte untersucht. Swift 4 verwendet die Typinferenz, um den entsprechenden Typ wie folgt zu ermitteln.

// varA is inferred to be of type Int
var varA = 42
print(varA)

// varB is inferred to be of type Double
var varB = 3.14159
print(varB)

// varC is also inferred to be of type Double
var varC = 3 + 0.14159
print(varC)

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

42
3.14159
3.14159

Eine Variable stellt uns einen benannten Speicher zur Verfügung, den unsere Programme bearbeiten können. Jede Variable in Swift 4 hat einen bestimmten Typ, der die Größe und das Layout des Speichers der Variablen bestimmt. den Wertebereich, der in diesem Speicher gespeichert werden kann; und die Menge von Operationen, die auf die Variable angewendet werden können.

Swift 4 unterstützt die folgenden grundlegenden Variablentypen:

  • Int or UInt- Dies wird für ganze Zahlen verwendet. Insbesondere können Sie Int32, Int64 verwenden, um eine vorzeichenbehaftete 32- oder 64-Bit-Ganzzahl zu definieren, während UInt32 oder UInt64, um vorzeichenlose 32- oder 64-Bit-Ganzzahlvariablen zu definieren. Zum Beispiel 42 und -23.

  • Float- Dies wird verwendet, um eine 32-Bit-Gleitkommazahl darzustellen. Es wird verwendet, um Zahlen mit kleineren Dezimalstellen zu halten. Zum Beispiel 3.14159, 0.1 und -273.158.

  • Double- Dies wird verwendet, um eine 64-Bit-Gleitkommazahl darzustellen, und wird verwendet, wenn Gleitkommawerte sehr groß sein müssen. Zum Beispiel 3.14159, 0.1 und -273.158.

  • Bool - Dies stellt einen booleschen Wert dar, der entweder wahr oder falsch ist.

  • String- Dies ist eine geordnete Sammlung von Zeichen. Zum Beispiel "Hallo Welt!"

  • Character- Dies ist ein einstelliges Zeichenfolgenliteral. Zum Beispiel "C"

Swift 4 ermöglicht es auch, verschiedene andere Arten von Variablen zu definieren, die wir in den folgenden Kapiteln behandeln werden, wie z Optional, Array, Dictionaries, Structures, und Classes.

Im folgenden Abschnitt wird beschrieben, wie Sie verschiedene Arten von Variablen in der Swift 4-Programmierung deklarieren und verwenden.

Variable Aussage

Eine Variablendeklaration teilt dem Compiler mit, wo und wie viel Speicher für die Variable erstellt werden soll. Bevor Sie Variablen verwenden, müssen Sie diese mit deklarierenvar Schlüsselwort wie folgt -

var variableName = <initial value>

Das folgende Beispiel zeigt, wie eine Variable in Swift 4 deklariert wird -

var varA = 42
print(varA)

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

42

Geben Sie Anmerkungen ein

Sie können eine type annotationWenn Sie eine Variable deklarieren, müssen Sie sich darüber im Klaren sein, welche Werte die Variable speichern kann. Hier ist die Syntax -

var variableName:<data type> = <optional initial value>

Das folgende Beispiel zeigt, wie eine Variable in Swift 4 mithilfe von Annotation deklariert wird. Hierbei ist zu beachten, dass, wenn wir keine Typanmerkung verwenden, die Angabe eines Anfangswertes für die Variable obligatorisch wird. Andernfalls können wir unsere Variable nur mithilfe der Typanmerkung deklarieren.

var varA = 42
print(varA)

var varB:Float

varB = 3.14159
print(varB)

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

42
3.1415901184082

Variablen benennen

Der Name einer Variablen kann aus Buchstaben, Ziffern und dem Unterstrich bestehen. Es muss entweder mit einem Buchstaben oder einem Unterstrich beginnen. Groß- und Kleinbuchstaben unterscheiden sich, da Swift 4 eine Programmiersprache ist, bei der zwischen Groß- und Kleinschreibung unterschieden wird.

Sie können einfache oder Unicode-Zeichen verwenden, um Ihre Variablen zu benennen. Das folgende Beispiel zeigt, wie Sie die Variablen benennen können -

var _var = "Hello, Swift 4!"
print(_var)

var 你好 = "你好世界"
print(你好)

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis.

Hello, Swift 4!
你好世界

Variablen drucken

Mit der Druckfunktion können Sie den aktuellen Wert einer Konstanten oder Variablen drucken. Sie können einen Variablenwert interpolieren, indem Sie den Namen in Klammern setzen und ihn vor der öffnenden Klammer mit einem Backslash maskieren: Es folgen gültige Beispiele:

var varA = "Godzilla"
var varB = 1000.00

print("Value of \(varA) is more than \(varB) millions")

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis.

Value of Godzilla is more than 1000.0 millions

Swift 4 stellt ebenfalls vor OptionalsTyp, der das Fehlen eines Werts behandelt. Optionale Optionen sagen entweder "es gibt einen Wert und er ist gleich x" oder "es gibt überhaupt keinen Wert".

Ein Optional ist ein Typ für sich, eigentlich eine der neuen Super-Power-Enums von Swift 4. Es hat zwei mögliche Werte:None und Some(T), wo T ist ein zugehöriger Wert des richtigen Datentyps, der in Swift 4 verfügbar ist.

Hier ist eine optionale Integer-Deklaration -

var perhapsInt: Int?

Hier ist eine optionale String-Deklaration -

var perhapsStr: String?

Die obige Deklaration entspricht einer expliziten Initialisierung nil was bedeutet, kein Wert -

var perhapsStr: String? = nil

Nehmen wir das folgende Beispiel, um zu verstehen, wie Optionen in Swift 4 funktionieren:

var myString:String? = nil

if myString != nil {
   print(myString)
} else {
   print("myString has nil value")
}

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

myString has nil value

Optionals ähneln der Verwendung nil mit Zeigern in Objective-C, aber sie funktionieren für jeden Typ, nicht nur für Klassen.

Erzwungenes Auspacken

Wenn Sie eine Variable als definiert haben optionalUm den Wert dieser Variablen zu erhalten, müssen Sie unwrapes. Dies bedeutet nur, ein Ausrufezeichen am Ende der Variablen zu setzen.

Nehmen wir ein einfaches Beispiel -

var myString:String?

myString = "Hello, Swift 4!"

if myString != nil {
   print(myString)
} else {
   print("myString has nil value")
}

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

Optional("Hello, Swift 4!")

Wenden wir nun das Auspacken an, um den korrekten Wert der Variablen zu erhalten -

var myString:String?

myString = "Hello, Swift 4!"

if myString != nil {
   print( myString! )
} else {
   print("myString has nil value")
}

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis.

Hello, Swift 4!

Automatisches Auspacken

Sie können optionale Variablen mit einem Ausrufezeichen anstelle eines Fragezeichens deklarieren. Solche optionalen Variablen werden automatisch entpackt und Sie müssen kein weiteres Ausrufezeichen am Ende der Variablen verwenden, um den zugewiesenen Wert zu erhalten. Nehmen wir ein einfaches Beispiel -

var myString:String!
myString = "Hello, Swift 4!"

if myString != nil {
   print(myString)
} else {
   print("myString has nil value")
}

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

Hello, Swift 4!

Optionale Bindung

Verwenden Sie die optionale Bindung, um herauszufinden, ob eine Option einen Wert enthält, und wenn ja, um diesen Wert als temporäre Konstante oder Variable verfügbar zu machen.

Eine optionale Bindung für die if Aussage ist wie folgt -

if let constantName = someOptional {
   statements
}

Nehmen wir ein einfaches Beispiel, um die Verwendung der optionalen Bindung zu verstehen.

var myString:String?
myString = "Hello, Swift 4!"

if let yourString = myString {
   print("Your string has - \(yourString)")
} else {
   print("Your string does not have a value")
}

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

Your string has - Hello, Swift 4!

Swift 4 stellt ebenfalls vor Tuples Typ, mit dem mehrere Werte in einem einzigen zusammengesetzten Wert gruppiert werden.

Die Werte in einem Tupel können von einem beliebigen Typ sein und müssen nicht vom gleichen Typ sein.

Beispielsweise ist ("Tutorials Point", 123) ein Tupel mit zwei Werten, einer vom Typ String und einer vom Typ Integer. Es ist ein rechtlicher Befehl.

let ImplementationError = (501, "Nicht implementiert") ist ein Fehler, wenn etwas auf dem Server nicht implementiert ist. Es werden zwei Werte zurückgegeben. Fehlercode und Beschreibung.

Sie können Tupel aus beliebig vielen Werten und aus einer beliebigen Anzahl unterschiedlicher Datentypen erstellen.

Hier ist die Syntax der Tupel-Deklaration:

var TupleName = (Value1, value2,… any number of values)

Hier ist eine Tupel-Erklärung -

var error501 = (501, “Not implemented”)

Sie können auf die Werte von Tupel zugreifen, indem Sie die Indexnummern verwenden, die bei 0 beginnen.

Hier ist ein Beispiel für den Zugriff auf Tupelwerte:

print(“The code is\(error501.0)”)
print(“The definition of error is\(error501.1)”)

Sie können die Variablen eines Tupels beim Deklarieren benennen und sie mit ihren Namen aufrufen

var error501 = (errorCode: 501, description: “Not Implemented”)
print(error501.errorCode)   // prints 501.

Tupel sind hilfreich, um mehrere Werte von einer Funktion zurückzugeben. Ebenso kann eine Webanwendung ein Tupel vom Typ ("String", Int) zurückgeben, um anzuzeigen, ob das Laden erfolgreich war oder fehlgeschlagen ist.

Durch die Rückgabe unterschiedlicher Werte in einem Tupel können wir Entscheidungen in Abhängigkeit von verschiedenen Tupeltypen treffen.

Note - Tupel sind nützlich für temporäre Werte und nicht für komplexe Daten geeignet.

Konstanten beziehen sich auf feste Werte, die ein Programm während seiner Ausführung möglicherweise nicht ändert. Konstanten können von einem der grundlegenden Datentypen sein, z. B. eine Ganzzahlkonstante, eine Floating-Konstante, eine Zeichenkonstante oder ein Zeichenfolgenliteral . Es gibt auch Aufzählungskonstanten .

Constants werden wie reguläre Variablen behandelt, mit der Ausnahme, dass ihre Werte nach ihrer Definition nicht mehr geändert werden können.

Konstantenerklärung

Bevor Sie Konstanten verwenden, müssen Sie sie mit deklarieren let Schlüsselwort wie folgt -

let constantName = <initial value>

Das folgende Beispiel zeigt, wie eine Konstante in Swift 4 deklariert wird:

let constA = 42
print(constA)

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

42

Geben Sie Anmerkungen ein

Sie können eine type annotationWenn Sie eine Konstante deklarieren, müssen Sie sich darüber im Klaren sein, welche Werte die Konstante speichern kann. Es folgt die Syntax -

var constantName:<data type> = <optional initial value>

Das folgende Beispiel zeigt, wie eine Konstante in Swift 4 mithilfe von Annotation deklariert wird. Hierbei ist zu beachten, dass beim Erstellen einer Konstante unbedingt ein Anfangswert angegeben werden muss -

let constA = 42
print(constA)

let constB:Float = 3.14159
print(constB)

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis.

42
3.1415901184082

Konstanten benennen

Der Name einer Konstante kann aus Buchstaben, Ziffern und dem Unterstrich bestehen. Es muss entweder mit einem Buchstaben oder einem Unterstrich beginnen. Groß- und Kleinbuchstaben unterscheiden sich, da Swift 4 eine Programmiersprache ist, bei der zwischen Groß- und Kleinschreibung unterschieden wird.

Sie können einfache oder Unicode-Zeichen verwenden, um Ihre Variablen zu benennen. Es folgen gültige Beispiele -

let _const = "Hello, Swift 4!"
print(_const)

let 你好 = "你好世界"
print(你好)

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

Hello, Swift 4!
你好世界

Konstanten drucken

Sie können den aktuellen Wert einer Konstanten oder Variablen mit drucken printFunktion. Sie können einen Variablenwert interpolieren, indem Sie den Namen in Klammern setzen und ihn vor der öffnenden Klammer mit einem Backslash maskieren: Es folgen gültige Beispiele:

let constA = "Godzilla"
let constB = 1000.00

print("Value of \(constA) is more than \(constB) millions")

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

Value of Godzilla is more than 1000.0 millions

Ein Literal ist die Quellcodedarstellung eines Werts einer Ganzzahl, einer Gleitkommazahl oder eines Zeichenfolgentyps. Das Folgende sind Beispiele für Literale -

42                // Integer literal
3.14159           // Floating-point literal
"Hello, world!"   // String literal

Ganzzahlige Literale

Ein ganzzahliges Literal kann eine Dezimal-, Binär-, Oktal- oder Hexadezimal-Konstante sein. Binäre Literale beginnen mit 0b, oktale Literale beginnen mit 0o und hexadezimale Literale beginnen mit 0x und nichts für Dezimalstellen.

Hier sind einige Beispiele für ganzzahlige Literale -

let decimalInteger = 17         // 17 in decimal notation
let binaryInteger = 0b10001     // 17 in binary notation
let octalInteger = 0o21         // 17 in octal notation
let hexadecimalInteger = 0x11   // 17 in hexadecimal notation

Gleitkomma-Literale

Ein Gleitkomma-Literal besteht aus einem ganzzahligen Teil, einem Dezimalpunkt, einem Bruchteil und einem Exponententeil. Sie können Gleitkomma-Literale entweder in Dezimalform oder in Hexadezimalform darstellen.

Dezimal-Gleitkomma-Literale bestehen aus einer Folge von Dezimalstellen, gefolgt von einem Dezimalbruch, einem Dezimal-Exponenten oder beidem.

Hexadezimale Gleitkomma-Literale bestehen aus einem 0x-Präfix, gefolgt von einem optionalen hexadezimalen Bruch, gefolgt von einem hexadezimalen Exponenten.

Hier einige Beispiele für Gleitkomma-Literale -

let decimalDouble = 12.1875
let exponentDouble = 1.21875e1
let hexadecimalDouble = 0xC.3p0

String-Literale

Ein Zeichenfolgenliteral ist eine Folge von Zeichen in doppelten Anführungszeichen mit der folgenden Form:

"characters"

String-Literale dürfen kein uneingeschränktes Anführungszeichen ("), einen nicht entkappten Backslash (\), einen Wagenrücklauf oder einen Zeilenvorschub enthalten. Sonderzeichen können in String-Literalen mithilfe der folgenden Escape-Sequenzen eingefügt werden:

Fluchtabfolge Bedeutung
\ 0 Nullzeichen
\\ \Charakter
\ b Rücktaste
\ f Formularvorschub
\ n Neue Zeile
\ r Wagenrücklauf
\ t Horizontale Registerkarte
\ v Vertikale Registerkarte
\ ' Einfaches Zitat
"" Doppeltes Zitat
\ 000 Oktalzahl von ein bis drei Ziffern
\ xhh ... Hexadezimalzahl aus einer oder mehreren Ziffern

Das folgende Beispiel zeigt, wie einige Zeichenfolgenliterale verwendet werden -

let stringL = "Hello\tWorld\n\nHello\'Swift 4\'"
print(stringL)

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

Hello World

Hello'Swift 4'

Boolesche Literale

Es gibt drei Boolesche Literale, die Teil der Standardschlüsselwörter von Swift 4 sind.

  • Ein Wert von true wahr darstellen.

  • Ein Wert von false falsch darstellen.

  • Ein Wert von nil keinen Wert darstellen.

Ein Operator ist ein Symbol, das den Compiler anweist, bestimmte mathematische oder logische Manipulationen durchzuführen. Objective-C ist reich an integrierten Operatoren und bietet die folgenden Arten von Operatoren:

  • Rechenzeichen
  • Vergleichsoperatoren
  • Logische Operatoren
  • Bitweise Operatoren
  • Zuweisungsoperatoren
  • Bereichsoperatoren
  • Verschiedene Operatoren

In diesem Tutorial werden die arithmetischen, relationalen, logischen, bitweisen, Zuweisungs- und anderen Operatoren nacheinander erläutert.

Rechenzeichen

Die folgende Tabelle zeigt alle arithmetischen Operatoren, die von der Sprache Swift 4 unterstützt werden. Variable annehmenA hält 10 und variabel B hält 20, dann -

Operator Description Example
+ Adds two operands A + B will give 30
Subtracts second operand from the first A − B will give -10
* Multiplies both operands A * B will give 200
/ Divides numerator by denominator B / A will give 2
% Modulus Operator and remainder of after an integer/float division B % A will give 0

Comparison Operators

The following table shows all the relational operators supported by Swift 4 language. Assume variable A holds 10 and variable B holds 20, then −

Operator Description Example
== Checks if the values of two operands are equal or not; if yes, then the condition becomes true. (A == B) is not true.
!= Checks if the values of two operands are equal or not; if values are not equal, then the condition becomes true. (A != B) is true.
> Checks if the value of left operand is greater than the value of right operand; if yes, then the condition becomes true. (A > B) is not true.
< Checks if the value of left operand is less than the value of right operand; if yes, then the condition becomes true. (A < B) is true.
>= Checks if the value of left operand is greater than or equal to the value of right operand; if yes, then the condition becomes true. (A >= B) is not true.
<= Checks if the value of left operand is less than or equal to the value of right operand; if yes, then the condition becomes true. (A <= B) is true.

Logical Operators

The following table shows all the logical operators supported by Swift 4 language. Assume variable A holds 1 and variable B holds 0, then −

Operator Description Example
&& Called Logical AND operator. If both the operands are non-zero, then the condition becomes true. (A && B) is false.
|| Called Logical OR Operator. If any of the two operands is non-zero, then the condition becomes true. (A || B) is true.
! Called Logical NOT Operator. Use to reverses the logical state of its operand. If a condition is true, then the Logical NOT operator will make it false. !(A && B) is true.

Bitwise Operators

Bitwise operators work on bits and perform bit by bit operation. The truth tables for &, |, and ^ are as follows −

p q p&q p|q p^q
0 0 0 0 0
0 1 0 1 1
1 1 1 1 0
1 0 0 1 1
Assume A = 60; and B = 13;

In binary format, they will be as follows:

A = 0011 1100

B = 0000 1101

-----------------

A & B = 0000 1100

A|B = 0011 1101

A^B = 0011 0001

~A = 1100 0011

Bitwise operators supported by Swift 4 language are listed in the following table. Assume variable A holds 60 and variable B holds 13, then 7−

Operator Description Example
& Binary AND Operator copies a bit to the result, if it exists in both operands. (A & B) will give 12, which is 0000 1100
| Binary OR Operator copies a bit, if it exists in either operand. (A | B) will give 61, which is 0011 1101
^ Binary XOR Operator copies the bit, if it is set in one operand but not both. (A ^ B) will give 49, which is 0011 0001
~ Binary Ones Complement Operator is unary and has the effect of 'flipping' bits. (~A ) will give -61, which is 1100 0011 in 2's complement form.
<< Binary Left Shift Operator. The left operands value is moved left by the number of bits specified by the right operand. (A << 2 will give 240, which is 1111 0000
>> Binary Right Shift Operator. The left operands value is moved right by the number of bits specified by the right operand. A >> 2 will give 15, which is 0000 1111

Assignment Operators

SSwift 4 supports the following assignment operators −

Operator Description Example
= Simple assignment operator, Assigns values from right side operands to left side operand C = A + B will assign value of A + B into C
+= Add AND assignment operator, It adds right operand to the left operand and assigns the result to left operand C += A is equivalent to C = C + A
-= Subtract AND assignment operator, It subtracts right operand from the left operand and assigns the result to left operand C -= A is equivalent to C = C - A
*= Multiply AND assignment operator, It multiplies right operand with the left operand and assigns the result to left operand C *= A is equivalent to C = C * A
/= Divide AND assignment operator, It divides left operand with the right operand and assigns the result to left operand C /= A is equivalent to C = C / A
%= Modulus AND assignment operator, It takes modulus using two operands and assigns the result to left operand C %= A is equivalent to C = C % A
<<= Left shift AND assignment operator C <<= 2 is same as C = C << 2
>>= Right shift AND assignment operator C >>= 2 is same as C = C >> 2
&= Bitwise AND assignment operator C &= 2 is same as C = C & 2
^= bitwise exclusive OR and assignment operator C ^= 2 is same as C = C ^ 2
|= bitwise inclusive OR and assignment operator C |= 2 is same as C = C | 2

Range Operators

Swift 4 includes two range operators, which are shortcuts for expressing a range of values. The following table explains these two operators.

Operator Description Example
Closed Range (a...b) defines a range that runs from a to b, and includes the values a and b. 1...5 gives 1, 2, 3, 4 and 5
Half-Open Range (a..< b) defines a range that runs from a to b, but does not include b. 1..< 5 gives 1, 2, 3, and 4
One- sided Range

a… , defines a range that runs from a to end of elements

…a , defines a range starting from start to a

1… gives 1 , 2,3… end of elements

…2 gives beginning… to 1,2

Misc Operators

Swift 4 supports a few other important operators including range and ? : which are explained in the following table.

Operator Description Example
Unary Minus The sign of a numeric value can be toggled using a prefixed - -3 or -4
Unary Plus Returns the value it operates on, without any change. +6 gives 6
Ternary Conditional Condition ? X : Y If Condition is true ? Then value X : Otherwise value Y

Operators Precedence

Operator precedence determines the grouping of terms in an expression. This affects how an expression is evaluated. Certain operators have higher precedence than others; for example, the multiplication operator has higher precedence than the addition operator.

For example, x = 7 + 3 * 2; here, x is assigned 13, not 20 because operator * has higher precedence than +, so it first gets multiplied with 3*2 and then adds into 7.

Here, operators with the highest precedence appear at the top of the table, those with the lowest appear at the bottom. Within an expression, higher precedence operators will be evaluated first.

Operator Description Example
Primary Expression Operators () [] . expr++ expr-- left-to-right
Unary Operators

* & + - ! ~ ++expr --expr

* / %

+ -

>> <<

< > <= >=

== !=

right-to-left
Binary Operators

&

^

|

&&

||

left-to-right
Ternary Operator ?: right-to-left
Assignment Operators = += -= *= /= %= >>= <<= &=^= |= right-to-left
Comma , left-to-right

Decision making structures require that the programmer specifies one or more conditions to be evaluated or tested by the program, along with a statement or statements to be executed if the condition is determined to be true, and optionally, other statements to be executed if the condition is determined to be false.

Following is the general from of a typical decision making structure found in most of the programming languages −

Swift 4 provides the following types of decision making statements. Click the following links to check their detail.

Sr.No Statement & Description
1 if statement

An if statement consists of a Boolean expression followed by one or more statements.

2 if...else statement

An if statement can be followed by an optional else statement, which executes when the Boolean expression is false.

3 if...else if...else Statement

An if statement can be followed by an optional else if...else statement, which is very useful to test various conditions using single if...else if statement.

4 nested if statements

You can use one if or else if statement inside another if or else if statement(s).

5 switch statement

A switch statement allows a variable to be tested for equality against a list of values.

The ? : Operator

We have covered conditional operator ? : in the previous chapter which can be used to replace if...else statements. It has the following general form −

Exp1 ? Exp2 : Exp3;

Where Exp1, Exp2, and Exp3 are expressions. Notice the use and placement of the colon.

The value of a ? expression is determined like this: Exp1 is evaluated. If it is true, then Exp2 is evaluated and becomes the value of the entire ? expression. If Exp1 is false, then Exp3 is evaluated and its value becomes the value of the expression.

There may be a situation when you need to execute a block of code several number of times. In general, statements are executed sequentially: The first statement in a function is executed first, followed by the second, and so on.

Programming languages provide various control structures that allow for more complicated execution paths.

A loop statement allows us to execute a statement or group of statements multiple times. Following is the general from of a loop statement in most of the programming languages −

Swift 4 programming language provides the following kinds of loop to handle looping requirements. Click the following links to check their detail.

Sr.No Loop Type & Description
1 for-in

This loop performs a set of statements for each item in a range, sequence, collection, or progression.

2 while loop

Repeats a statement or group of statements while a given condition is true. It tests the condition before executing the loop body.

3 repeat...while loop

Like a while statement, except that it tests the condition at the end of the loop body.

Loop Control Statements

Loop control statements change execution from its normal sequence. When execution leaves a scope, all automatic objects that were created in that scope are destroyed.

Swift 4 supports the following control statements. Click the following links to check their detail.

Sr.No Control Statement & Description
1 continue statement

This statement tells a loop to stop what it is doing and start again at the beginning of the next iteration through the loop.

2 break statement

Terminates the loop statement and transfers execution to the statement immediately following the loop.

3 fallthrough statement

The fallthrough statement simulates the behavior of Swift 4 switch to C-style switch.

Strings in Swift 4 are an ordered collection of characters, such as "Hello, World!" and they are represented by the Swift 4 data type String, which in turn represents a collection of values of Character type.

Create a String

You can create a String either by using a string literal or creating an instance of a String class as follows −

// String creation using String literal
var stringA = "Hello, Swift 4!"
print( stringA )

// String creation using String instance
var stringB = String("Hello, Swift 4!")
print( stringB )

//Multiple line string

let stringC = """
Hey this is a
example of multiple Line
string by tutorialsPoint 

"""
print(stringC)

When the above code is compiled and executed, it produces the following result

Hello, Swift 4!
Hello, Swift 4!
Hey this is a
example of multiple Line
string by tutorialsPoint

Empty String

You can create an empty String either by using an empty string literal or creating an instance of String class as shown below. You can also check whether a string is empty or not using the Boolean property isEmpty.

// Empty string creation using String literal
var stringA = ""

if stringA.isEmpty {
   print( "stringA is empty" )
} else {
   print( "stringA is not empty" )
}

// Empty string creation using String instance
let stringB = String()

if stringB.isEmpty {
   print( "stringB is empty" )
} else {
   print( "stringB is not empty" )
}

When the above code is compiled and executed, it produces the following result −

stringA is empty
stringB is empty

String Constants

You can specify whether your String can be modified (or mutated) by assigning it to a variable, or it will be constant by assigning it to a constant using let keyword as shown below −

// stringA can be modified
var stringA = "Hello, Swift 4!"
stringA + = "--Readers--"
print( stringA )

// stringB can not be modified
let stringB = String("Hello, Swift 4!")
stringB + = "--Readers--"
print( stringB )

Wenn der obige Code kompiliert und ausgeführt wird, ergibt sich das folgende Ergebnis:

Playground execution failed: error: <EXPR>:10:1: error: 'String' is not
convertible to '@lvalue UInt8'
stringB + = "--Readers--"

String-Interpolation

Die String-Interpolation ist eine Möglichkeit, einen neuen String-Wert aus einer Mischung von Konstanten, Variablen, Literalen und Ausdrücken zu erstellen, indem deren Werte in ein String-Literal eingefügt werden.

Jedes Element (Variable oder Konstante), das Sie in das Zeichenfolgenliteral einfügen, wird in zwei Klammern eingeschlossen, denen ein Backslash vorangestellt ist. Hier ist ein einfaches Beispiel -

var varA = 20
let constA = 100
var varC:Float = 20.0

var stringA = "\(varA) times \(constA) is equal to \(varC * 100)"
print( stringA )

Wenn der obige Code kompiliert und ausgeführt wird, ergibt sich das folgende Ergebnis:

20 times 100 is equal to 2000.0

String-Verkettung

Mit dem Operator + können Sie zwei Zeichenfolgen oder eine Zeichenfolge und ein Zeichen oder zwei Zeichen verketten. Hier ist ein einfaches Beispiel -

let constA = "Hello,"
let constB = "World!"

var stringA = constA + constB
print( stringA )

Wenn der obige Code kompiliert und ausgeführt wird, ergibt sich das folgende Ergebnis:

Hello,World!

String-Länge

Swift 4 Saiten haben keine lengthEigenschaft, aber Sie können die globale count () -Funktion verwenden, um die Anzahl der Zeichen in einer Zeichenfolge zu zählen. Hier ist ein einfaches Beispiel -

var varA = "Hello, Swift 4!"

print( "\(varA), length is \((varA.count))" )

Wenn der obige Code kompiliert und ausgeführt wird, ergibt sich das folgende Ergebnis:

Hello, Swift 4!, length is 15

String-Vergleich

Mit dem Operator == können Sie zwei Zeichenfolgenvariablen oder -konstanten vergleichen. Hier ist ein einfaches Beispiel -

var varA = "Hello, Swift 4!"
var varB = "Hello, World!"

if varA == varB {
   print( "\(varA) and \(varB) are equal" )
} else {
   print( "\(varA) and \(varB) are not equal" )
}

Wenn der obige Code kompiliert und ausgeführt wird, ergibt sich das folgende Ergebnis:

Hello, Swift 4! and Hello, World! are not equal

String Iterieren

Strings sind wieder eine Sammlung von Werten in Swift 4, sodass wir mithilfe von Schleifen über Strings iterieren können. - -

for chars in "ThisString" {
   print(chars, terminator: " ")
}

Wenn der obige Code kompiliert und ausgeführt wird, ergibt sich das folgende Ergebnis:

T h i s S t r i n g

Unicode-Zeichenfolgen

Sie können auf eine UTF-8- und UTF-16-Darstellung eines Strings zugreifen, indem Sie die Eigenschaften utf8 und utf16 durchlaufen, wie im folgenden Beispiel gezeigt.

var unicodeString = "Dog???"

print("UTF-8 Codes: ")
for code in unicodeString.utf8 {
   print("\(code) ")
}

print("\n")

print("UTF-16 Codes: ")
for code in unicodeString.utf16 {
   print("\(code) ")
}

Wenn der obige Code kompiliert und ausgeführt wird, ergibt sich das folgende Ergebnis:

UTF-8 Codes: 
68 
111 
103 
63 
63 
63 


UTF-16 Codes: 
68 
111 
103 
63 
63 
63

String-Funktionen und Operatoren

Swift 4 unterstützt eine Vielzahl von Methoden und Operatoren im Zusammenhang mit Strings -

Sr.Nr. Funktionen / Operatoren & Zweck
1

isEmpty

Ein boolescher Wert, der bestimmt, ob eine Zeichenfolge leer ist oder nicht.

2

hasPrefix(prefix: String)

Funktion zum Überprüfen, ob eine bestimmte Parameterzeichenfolge als Präfix der Zeichenfolge vorhanden ist oder nicht.

3

hasSuffix(suffix: String)

Funktion zum Überprüfen, ob eine bestimmte Parameterzeichenfolge als Suffix der Zeichenfolge vorhanden ist oder nicht.

4

toInt()

Funktion zum Konvertieren eines numerischen String-Werts in eine Ganzzahl.

5

count()

Globale Funktion zum Zählen der Anzahl der Zeichen in einer Zeichenfolge.

6

utf8

Eigenschaft zum Zurückgeben einer UTF-8-Darstellung einer Zeichenfolge.

7

utf16

Eigenschaft zum Zurückgeben einer UTF-16-Darstellung einer Zeichenfolge.

8

unicodeScalars

Eigenschaft zum Zurückgeben einer Unicode-Skalardarstellung einer Zeichenfolge.

9

+

Operator zum Verketten von zwei Zeichenfolgen oder einer Zeichenfolge und einem Zeichen oder zwei Zeichen.

10

+=

Operator zum Anhängen einer Zeichenfolge oder eines Zeichens an eine vorhandene Zeichenfolge.

11

==

Operator zum Bestimmen der Gleichheit zweier Zeichenfolgen.

12

<

Der Operator führt einen lexikografischen Vergleich durch, um festzustellen, ob eine Zeichenfolge weniger als eine andere auswertet.

13

startIndex

Um den Wert am Startindex der Zeichenfolge zu erhalten.

14

endIndex

Um den Wert am Endindex der Zeichenfolge zu erhalten.

15

Indices

Zugriff auf die Indeces nacheinander. dh alle Zeichen der Zeichenfolge einzeln.

16

insert("Value", at: position)

Einfügen eines Wertes an einer Position.

17

remove(at: position)

removeSubrange(range)

um einen Wert an einer Position zu entfernen oder um einen Wertebereich aus der Zeichenfolge zu entfernen.

18

reversed()

Gibt die Umkehrung eines Strings zurück

EIN character in Swift ist ein einstelliges String-Literal, das vom Datentyp adressiert wird Character. Schauen Sie sich das folgende Beispiel an. Es werden zwei Zeichenkonstanten verwendet -

let char1: Character = "A"
let char2: Character = "B"

print("Value of char1 \(char1)")
print("Value of char2 \(char2)")

Wenn der obige Code kompiliert und ausgeführt wird, ergibt sich das folgende Ergebnis:

Value of char1 A
Value of char2 B

Wenn Sie versuchen, mehr als ein Zeichen in einer Zeichentypvariablen oder -konstante zu speichern, lässt Swift 4 dies nicht zu. Wenn Sie das folgende Beispiel in Swift 4 Playground eingeben, wird bereits vor dem Kompilieren eine Fehlermeldung angezeigt.

// Following is wrong in Swift 4
let char: Character = "AB"

print("Value of char \(char)")

Leere Zeichenvariablen

Es ist nicht möglich, eine leere Zeichenvariable oder -konstante mit einem leeren Wert zu erstellen. Die folgende Syntax ist nicht möglich -

// Following is wrong in Swift 4
let char1: Character = ""
var char2: Character = ""

print("Value of char1 \(char1)")
print("Value of char2 \(char2)")

Zugriff auf Zeichen über Zeichenfolgen

Wie bei der Erörterung der Strings von Swift 4 erläutert, repräsentiert String eine Sammlung von Zeichenwerten in einer bestimmten Reihenfolge. Wir können also auf einzelne Zeichen aus dem angegebenen String zugreifen, indem wir diesen String mit einem durchlaufenfor-in Schleife -

for ch in "Hello" {
   print(ch)
}

Wenn der obige Code kompiliert und ausgeführt wird, ergibt sich das folgende Ergebnis:

H
e
l
l
o

Verketten von Zeichenfolgen mit Zeichen

Das folgende Beispiel zeigt, wie der Charakter eines Swift 4 mit dem String von Swift 4 verkettet werden kann.

var varA:String = "Hello "
let varB:Character = "G"

varA.append( varB )

print("Value of varC = \(varA)")

Wenn der obige Code kompiliert und ausgeführt wird, ergibt sich das folgende Ergebnis:

Value of varC = Hello G

Swift 4-Arrays werden zum Speichern geordneter Wertelisten desselben Typs verwendet. Swift 4 führt eine strenge Überprüfung durch, bei der Sie auch aus Versehen keinen falschen Typ in ein Array eingeben können.

Wenn Sie einer Variablen ein erstelltes Array zuweisen, ist es immer veränderbar. Dies bedeutet, dass Sie es ändern können, indem Sie seine Elemente hinzufügen, entfernen oder ändern. Wenn Sie jedoch einer Konstanten ein Array zuweisen, ist dieses Array unveränderlich und seine Größe und sein Inhalt können nicht geändert werden.

Arrays erstellen

Sie können ein leeres Array eines bestimmten Typs mithilfe der folgenden Initialisierersyntax erstellen:

var someArray = [SomeType]()

Hier ist die Syntax, um ein Array mit einer bestimmten Größe a * zu erstellen und es mit einem Wert zu initialisieren -

var someArray = [SomeType](count: NumbeOfElements, repeatedValue: InitialValue)

Mit der folgenden Anweisung können Sie ein leeres Array von erstellen Int Typ mit 3 Elementen und dem Anfangswert Null -

var someInts = [Int](count: 3, repeatedValue: 0)

Im Folgenden finden Sie ein weiteres Beispiel, um ein Array mit drei Elementen zu erstellen und diesem Array drei Werte zuzuweisen:

var someInts:[Int] = [10, 20, 30]

Zugriff auf Arrays

Mit können Sie einen Wert aus einem Array abrufen subscript Syntax: Übergeben Sie den Index des Werts, den Sie abrufen möchten, in eckigen Klammern unmittelbar nach dem Namen des Arrays wie folgt:

var someVar = someArray[index]

Hier das indexbeginnt bei 0, was bedeutet, dass auf das erste Element mit dem Index als 0 zugegriffen werden kann, auf das zweite Element mit dem Index als 1 usw. zugegriffen werden kann. Das folgende Beispiel zeigt, wie Sie Arrays erstellen, initialisieren und darauf zugreifen.

var someInts = [Int](count: 3, repeatedValue: 10)

var someVar = someInts[0]
print( "Value of first element is \(someVar)" )
print( "Value of second element is \(someInts[1])" )
print( "Value of third element is \(someInts[2])" )

Wenn der obige Code kompiliert und ausgeführt wird, ergibt sich das folgende Ergebnis:

Value of first element is 10
Value of second element is 10
Value of third element is 10

Arrays ändern

Sie können verwenden append()Methoden- oder Additionszuweisungsoperator (+ =) zum Hinzufügen eines neuen Elements am Ende eines Arrays. Schauen Sie sich das folgende Beispiel an. Hier erstellen wir zunächst ein leeres Array und fügen dann neue Elemente zum selben Array hinzu -

var someInts = [Int]()

someInts.append(20)
someInts.append(30)
someInts += [40]

var someVar = someInts[0]

print( "Value of first element is \(someVar)" )
print( "Value of second element is \(someInts[1])" )
print( "Value of third element is \(someInts[2])" )

Wenn der obige Code kompiliert und ausgeführt wird, ergibt sich das folgende Ergebnis:

Value of first element is 20
Value of second element is 30
Value of third element is 40

Sie können ein vorhandenes Element eines Arrays ändern, indem Sie einem bestimmten Index einen neuen Wert zuweisen, wie im folgenden Beispiel gezeigt.

var someInts = [Int]()

someInts.append(20)
someInts.append(30)
someInts += [40]

// Modify last element
someInts[2] = 50

var someVar = someInts[0]

print( "Value of first element is \(someVar)" )
print( "Value of second element is \(someInts[1])" )
print( "Value of third element is \(someInts[2])" )

Wenn der obige Code kompiliert und ausgeführt wird, ergibt sich das folgende Ergebnis:

Value of first element is 20
Value of second element is 30
Value of third element is 50

Iterieren über ein Array

Sie können verwenden for-in Schleife, um den gesamten Wertesatz in einem Array zu durchlaufen, wie im folgenden Beispiel gezeigt -

var someStrs = [String]()

someStrs.append("Apple")
someStrs.append("Amazon")
someStrs += ["Google"]
for item in someStrs {
   print(item)
}

Wenn der obige Code kompiliert und ausgeführt wird, ergibt sich das folgende Ergebnis:

Apple
Amazon
Google

Sie können verwenden enumerate() Funktion, die den Index eines Elements zusammen mit seinem Wert zurückgibt, wie unten im folgenden Beispiel gezeigt -

var someStrs = [String]()

someStrs.append("Apple")
someStrs.append("Amazon")
someStrs += ["Google"]

for (index, item) in someStrs.enumerated() {
   print("Value at index = \(index) is \(item)")
}

Wenn der obige Code kompiliert und ausgeführt wird, ergibt sich das folgende Ergebnis:

Value at index = 0 is Apple
Value at index = 1 is Amazon
Value at index = 2 is Google

Hinzufügen von zwei Arrays

Mit dem Additionsoperator (+) können Sie zwei Arrays desselben Typs hinzufügen, wodurch ein neues Array mit einer Kombination von Werten aus den beiden Arrays wie folgt erhalten wird:

var intsA = [Int](count:2, repeatedValue: 2)
var intsB = [Int](count:3, repeatedValue: 1)

var intsC = intsA + intsB
for item in intsC {
   print(item)
}

Wenn der obige Code kompiliert und ausgeführt wird, ergibt sich das folgende Ergebnis:

2
2
1
1
1

Die count-Eigenschaft

Sie können schreibgeschützt verwenden count Eigenschaft eines Arrays, um die Anzahl der Elemente in einem unten gezeigten Array herauszufinden -

var intsA = [Int](count:2, repeatedValue: 2)
var intsB = [Int](count:3, repeatedValue: 1)

var intsC = intsA + intsB

print("Total items in intsA = \(intsA.count)")
print("Total items in intsB = \(intsB.count)")
print("Total items in intsC = \(intsC.count)")

Wenn der obige Code kompiliert und ausgeführt wird, ergibt sich das folgende Ergebnis:

Total items in intsA = 2
Total items in intsB = 3
Total items in intsC = 5

Die leere Eigenschaft

Sie können schreibgeschützt verwenden empty Eigenschaft eines Arrays, um herauszufinden, ob ein Array leer ist oder nicht, wie unten gezeigt -

var intsA = [Int](count:2, repeatedValue: 2)
var intsB = [Int](count:3, repeatedValue: 1)
var intsC = [Int]()

print("intsA.isEmpty = \(intsA.isEmpty)")
print("intsB.isEmpty = \(intsB.isEmpty)")
print("intsC.isEmpty = \(intsC.isEmpty)")

Wenn der obige Code kompiliert und ausgeführt wird, ergibt sich das folgende Ergebnis:

intsA.isEmpty = false
intsB.isEmpty = false
intsC.isEmpty = true

Swift 4 sets werden verwendet, um unterschiedliche Werte desselben Typs zu speichern, haben jedoch keine eindeutige Reihenfolge wie Arrays.

Sie können Mengen anstelle von Arrays verwenden, wenn die Reihenfolge der Elemente kein Problem darstellt oder wenn Sie sicherstellen möchten, dass keine doppelten Werte vorhanden sind. (Sätze erlauben nur unterschiedliche Werte.)

Ein Typ muss hashbar sein, um in einem Set gespeichert zu werden. Ein Hash-Wert ist ein Int-Wert, der für gleiche Objekte gleich ist. Zum Beispiel, wenn x == y, dannx.hashvalue == y.hashvalue.

Alle grundlegenden Swift-Werte sind standardmäßig vom Typ Hashable und können als Set-Werte verwendet werden.

Sets erstellen

Sie können eine leere Menge eines bestimmten Typs mit der folgenden Initialisierersyntax erstellen:

var someSet = Set<Character>()     //Character can be replaced by data type of set.

Zugreifen auf und Ändern von Sets

Sie können mithilfe der Methoden und Eigenschaften auf einen Satz zugreifen oder ihn ändern.

Die "count" -Methode kann verwendet werden, um die Anzahl der Elemente in der Menge anzuzeigen.

someSet.count        // prints the number of elements

Die Methode "Einfügen" kann verwendet werden, um Werte in den Satz einzufügen.

someSet.insert("c")   // adds the element to Set.

In ähnlicher Weise kann mit isEmpty überprüft werden, ob set leer ist.

someSet.isEmpty       // returns true or false depending on the set Elements.

Die Methode "remove" kann verwendet werden, um den Wert im Satz zu entfernen.

someSet.remove("c")     // removes a element , removeAll() can be used to remove all elements

Die Methode "enthält" kann verwendet werden, um das Vorhandensein eines Werts in einer Menge zu überprüfen.

someSet.contains("c")     // to check if set contains this value.

Iterieren über ein Set

Sie können einen Satz mit der for-in-Schleife durchlaufen -

for items in someSet {
   print(someSet)
}

//Swift sets are not in an ordered way, to iterate over a set in ordered way use

for items in someSet.sorted() {
   print(someSet)
}

Set-Operationen ausführen

Sie können grundlegende Set-Operationen für schnelle Sets ausführen.

Im Folgenden finden Sie die Methoden zum Ausführen von Set-Operationen:

  • Intersection
  • Union
  • subtracting
let evens: Set = [10,12,14,16,18]
let odds: Set = [5,7,9,11,13]
let primes = [2,3,5,7]
odds.union(evens).sorted()
// [5,7,9,10,11,12,13,14,16,18]
odds.intersection(evens).sorted()
//[]
odds.subtracting(primes).sorted()
//[9, 11, 13]

Swift 4 dictionarieswerden verwendet, um ungeordnete Listen von Werten desselben Typs zu speichern. Swift 4 führt eine strenge Überprüfung durch, die es Ihnen nicht erlaubt, versehentlich einen falschen Typ in ein Wörterbuch einzugeben.

Swift 4-Wörterbücher verwenden eine eindeutige Kennung, die als a bezeichnet wird keyum einen Wert zu speichern, auf den später verwiesen und über denselben Schlüssel nachgeschlagen werden kann. Im Gegensatz zu Elementen in einem Array sind Elemente in adictionaryhabe keine bestimmte Reihenfolge. Sie können eine verwendendictionary wenn Sie Werte anhand ihrer Bezeichner nachschlagen müssen.

Ein Wörterbuchschlüssel kann entweder eine Ganzzahl oder eine Zeichenfolge ohne Einschränkung sein, sollte jedoch innerhalb eines Wörterbuchs eindeutig sein.

Wenn Sie einer Variablen ein erstelltes Wörterbuch zuweisen, ist es immer veränderbar. Dies bedeutet, dass Sie es ändern können, indem Sie seine Elemente hinzufügen, entfernen oder ändern. Wenn Sie jedoch einer Konstante ein Wörterbuch zuweisen, ist dieses Wörterbuch unveränderlich und seine Größe und sein Inhalt können nicht geändert werden.

Wörterbuch erstellen

Sie können ein leeres Wörterbuch eines bestimmten Typs mit der folgenden Initialisierersyntax erstellen:

var someDict = [KeyType: ValueType]()

Mit der folgenden einfachen Syntax können Sie ein leeres Wörterbuch erstellen, dessen Schlüssel vom Typ Int ist und dessen zugehörige Werte Zeichenfolgen sind.

var someDict = [Int: String]()

Hier ist ein Beispiel zum Erstellen eines Wörterbuchs aus einer Reihe vorgegebener Werte:

var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]

Sequenzbasierte Initialisierung

Mit Swift 4 können Sie ein Wörterbuch aus Arrays erstellen (Schlüssel-Wert-Paare).

var cities = [“Delhi”,”Bangalore”,”Hyderabad”]

Mit der folgenden einfachen Syntax können Sie ein leeres Wörterbuch erstellen, dessen Schlüssel vom Typ Int ist und dessen zugehörige Werte Zeichenfolgen sind.

var Distance = [2000,10, 620]

Hier ist ein Beispiel zum Erstellen eines Wörterbuchs aus einer Reihe vorgegebener Werte:

let cityDistanceDict = Dictionary(uniqueKeysWithValues: zip(cities, Distance))

Mit den obigen Codezeilen wird ein Wörterbuch mit Städten als Schlüssel und Entfernung als Wert erstellt.

Filtern

Mit Swift 4 können Sie Werte aus einem Wörterbuch filtern.

var closeCities = cityDistanceDict.filter { $0.value < 1000 }

Wenn wir den obigen Code ausführen, ist unser closeCities-Wörterbuch.

["Bangalore" : 10 , "Hyderabad" : 620]

Wörterbuchgruppierung

Mit Swift 4 können Sie eine Gruppierung von Wörterbuchwerten erstellen.

var cities = ["Delhi","Bangalore","Hyderabad","Dehradun","Bihar"]

Mit der folgenden einfachen Syntax können Sie die Werte des Wörterbuchs nach dem ersten Alphabet gruppieren.

var GroupedCities = Dictionary(grouping: cities ) { $0.first! }

Das Ergebnis des obigen Codes wird sein

["D" :["Delhi","Dehradun"], "B" : ["Bengaluru","Bihar"], "H" : ["Hyderabad"]]

Zugriff auf Wörterbücher

Sie können einen Wert aus einem Wörterbuch abrufen, indem Sie die tiefgestellte Syntax verwenden und den Schlüssel des Werts, den Sie abrufen möchten, in eckigen Klammern unmittelbar nach dem Namen des Wörterbuchs wie folgt übergeben:

var someVar = someDict[key]

Sehen wir uns das folgende Beispiel an, um Werte aus einem Wörterbuch zu erstellen, zu initialisieren und darauf zuzugreifen:

var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
var someVar = someDict[1]

print( "Value of key = 1 is \(someVar)" )
print( "Value of key = 2 is \(someDict[2])" )
print( "Value of key = 3 is \(someDict[3])" )

Wenn der obige Code kompiliert und ausgeführt wird, ergibt sich das folgende Ergebnis:

Value of key = 1 is Optional("One")
Value of key = 2 is Optional("Two")
Value of key = 3 is Optional("Three")

Wörterbücher ändern

Sie können verwenden updateValue(forKey:)Methode zum Hinzufügen eines vorhandenen Werts zu einem bestimmten Schlüssel des Wörterbuchs. Diese Methode gibt einen optionalen Wert des Wertetyps des Wörterbuchs zurück. Hier ist ein einfaches Beispiel -

var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
var oldVal = someDict.updateValue("New value of one", forKey: 1)
var someVar = someDict[1]

print( "Old value of key = 1 is \(oldVal)" )
print( "Value of key = 1 is \(someVar)" )
print( "Value of key = 2 is \(someDict[2])" )
print( "Value of key = 3 is \(someDict[3])" )

Wenn der obige Code kompiliert und ausgeführt wird, ergibt sich das folgende Ergebnis:

Old value of key = 1 is Optional("One")
Value of key = 1 is Optional("New value of one")
Value of key = 2 is Optional("Two")
Value of key = 3 is Optional("Three")

Sie können ein vorhandenes Element eines Wörterbuchs ändern, indem Sie einem bestimmten Schlüssel einen neuen Wert zuweisen, wie im folgenden Beispiel gezeigt.

var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
var oldVal = someDict[1]
someDict[1] = "New value of one"
var someVar = someDict[1]

print( "Old value of key = 1 is \(oldVal)" )
print( "Value of key = 1 is \(someVar)" )
print( "Value of key = 2 is \(someDict[2])" )
print( "Value of key = 3 is \(someDict[3])" )

Wenn der obige Code kompiliert und ausgeführt wird, ergibt sich das folgende Ergebnis:

Old value of key = 1 is Optional("One")
Value of key = 1 is Optional("New value of one")
Value of key = 2 is Optional("Two")
Value of key = 3 is Optional("Three")

Schlüsselwertpaare entfernen

Sie können verwenden removeValueForKey()Methode zum Entfernen eines Schlüssel-Wert-Paares aus einem Wörterbuch. Diese Methode entfernt das Schlüssel-Wert-Paar, falls vorhanden, und gibt den entfernten Wert zurück, oder gibt nil zurück, wenn kein Wert vorhanden ist. Hier ist ein einfaches Beispiel -

var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
var removedValue = someDict.removeValue(forKey: 2)

print( "Value of key = 1 is \(someDict[1])" )
print( "Value of key = 2 is \(someDict[2])" )
print( "Value of key = 3 is \(someDict[3])" )

Wenn der obige Code kompiliert und ausgeführt wird, ergibt sich das folgende Ergebnis:

Value of key = 1 is Optional("One")
Value of key = 2 is nil
Value of key = 3 is Optional("Three")

Sie können auch die tiefgestellte Syntax verwenden, um ein Schlüssel-Wert-Paar aus einem Wörterbuch zu entfernen, indem Sie einen Wert von zuweisen nilfür diesen Schlüssel. Hier ist ein einfaches Beispiel -

var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]

someDict[2] = nil

print( "Value of key = 1 is \(someDict[1])" )
print( "Value of key = 2 is \(someDict[2])" )
print( "Value of key = 3 is \(someDict[3])" )

Wenn der obige Code kompiliert und ausgeführt wird, ergibt sich das folgende Ergebnis:

Value of key = 1 is Optional("One")
Value of key = 2 is nil
Value of key = 3 is Optional("Three")

Durch ein Wörterbuch iterieren

Sie können eine verwenden for-in Schleife, um den gesamten Satz von Schlüssel-Wert-Paaren in einem Wörterbuch zu durchlaufen, wie im folgenden Beispiel gezeigt -

var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]

for (index, keyValue) in someDict.enumerated() {
   print("Dictionary key \(index) - Dictionary value \(keyValue)")
}

Wenn der obige Code kompiliert und ausgeführt wird, ergibt sich das folgende Ergebnis:

Dictionary key 2 - Dictionary value Two
Dictionary key 3 - Dictionary value Three
Dictionary key 1 - Dictionary value One

Sie können verwenden enumerate() Funktion, die den Index des Elements zusammen mit seinem Paar (Schlüssel, Wert) zurückgibt, wie unten im Beispiel gezeigt -

var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
for (key, value) in someDict.enumerated() {
   print("Dictionary key \(key) - Dictionary value \(value)")
}

Wenn der obige Code kompiliert und ausgeführt wird, ergibt sich das folgende Ergebnis:

Dictionary key 0 - Dictionary value (key: 2, value: "Two")
Dictionary key 1 - Dictionary value (key: 3, value: "Three")
Dictionary key 2 - Dictionary value (key: 1, value: "One")

In Arrays konvertieren

Sie können eine Liste von Schlüssel-Wert-Paaren aus einem bestimmten Wörterbuch extrahieren, um separate Arrays für Schlüssel und Werte zu erstellen. Hier ist ein Beispiel -

var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]

let dictKeys = [Int](someDict.keys)
let dictValues = [String](someDict.values)

print("Print Dictionary Keys")

for (key) in dictKeys {
   print("\(key)")
}
print("Print Dictionary Values")

for (value) in dictValues {
   print("\(value)")
}

Wenn der obige Code kompiliert und ausgeführt wird, ergibt sich das folgende Ergebnis:

Print Dictionary Keys
2
3
1
Print Dictionary Values
Two
Three
One

Die count-Eigenschaft

Sie können schreibgeschützt verwenden count Eigenschaft eines Wörterbuchs, um die Anzahl der Elemente in einem Wörterbuch wie unten gezeigt herauszufinden -

var someDict1:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
var someDict2:[Int:String] = [4:"Four", 5:"Five"]

print("Total items in someDict1 = \(someDict1.count)")
print("Total items in someDict2 = \(someDict2.count)")

Wenn der obige Code kompiliert und ausgeführt wird, ergibt sich das folgende Ergebnis:

Total items in someDict1 = 3
Total items in someDict2 = 2

Die leere Eigenschaft

Sie können schreibgeschützt verwenden empty Eigenschaft eines Wörterbuchs, um herauszufinden, ob ein Wörterbuch leer ist oder nicht, wie unten gezeigt -

var someDict1:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
var someDict2:[Int:String] = [4:"Four", 5:"Five"]
var someDict3:[Int:String] = [Int:String]()

print("someDict1 = \(someDict1.isEmpty)")
print("someDict2 = \(someDict2.isEmpty)")
print("someDict3 = \(someDict3.isEmpty)")

Wenn der obige Code kompiliert und ausgeführt wird, ergibt sich das folgende Ergebnis:

someDict1 = false
someDict2 = false
someDict3 = true

Eine Funktion ist eine Reihe von Anweisungen, die zusammen organisiert sind, um eine bestimmte Aufgabe auszuführen. Eine Swift 4-Funktion kann so einfach wie eine einfache C-Funktion oder so komplex wie eine Objective C-Sprachfunktion sein. Es ermöglicht uns, lokale und globale Parameterwerte innerhalb der Funktionsaufrufe zu übergeben.

  • Function Declaration - informiert den Compiler über den Namen, den Rückgabetyp und die Parameter einer Funktion.

  • Function Definition - Es liefert den eigentlichen Funktionskörper.

Swift 4-Funktionen enthalten den Parametertyp und seine Rückgabetypen.

Funktionsdefinition

In Swift 4 wird eine Funktion durch das Schlüsselwort "func" definiert. Wenn eine Funktion neu definiert wird, kann sie einen oder mehrere Werte als Eingabeparameter für die Funktion verwenden. Sie verarbeitet die Funktionen im Hauptteil und gibt die Werte als Ausgabe-Rückgabetypen an die Funktionen zurück.

Jede Funktion hat einen Funktionsnamen, der die von der Funktion ausgeführte Aufgabe beschreibt. Um eine Funktion zu verwenden, "rufen" Sie diese Funktion mit ihrem Namen auf und übergeben Eingabewerte (sogenannte Argumente), die den Typen der Funktionsparameter entsprechen. Funktionsparameter werden auch als "Tupel" bezeichnet.

Die Argumente einer Funktion müssen immer in derselben Reihenfolge wie die Parameterliste der Funktion angegeben werden. Auf die Rückgabewerte folgt →.

Syntax

func funcname(Parameters) -> returntype {
   Statement1
   Statement2
   ---
   Statement N
   return parameters
}

Schauen Sie sich den folgenden Code an. Der Name des Schülers wird als String-Datentyp deklariert, der in der Funktion 'student' deklariert ist. Wenn die Funktion aufgerufen wird, wird der Name des Schülers zurückgegeben.

func student(name: String) -> String {
   return name
}

print(student(name: "First Program"))
print(student(name: "About Functions"))

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

First Program
About Functions

Eine Funktion aufrufen

Nehmen wir an, wir haben eine Funktion namens 'display' definiert, um beispielsweise die Zahlen anzuzeigen. Eine Funktion mit dem Funktionsnamen 'display' wird zuerst mit dem Argument 'no1' initialisiert, das den Integer-Datentyp enthält. Dann wird das Argument 'no1' dem Argument 'a' zugewiesen, das im Folgenden auf dieselbe Datentyp-Ganzzahl verweist. Jetzt wird das Argument 'a' an die Funktion zurückgegeben. Hier enthält die Funktion display () den ganzzahligen Wert und gibt die ganzzahligen Werte zurück, wenn die Funktion jedes Mal aufgerufen wird.

func display(no1: Int) -> Int {
   let a = no1
   return a
}

print(display(no1: 100))
print(display(no1: 200))

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

100
200

Parameter und Rückgabewerte

Swift 4 bietet flexible Funktionsparameter und deren Rückgabewerte von einfachen bis zu komplexen Werten. Ähnlich wie bei C und Ziel C können Funktionen in Swift 4 auch verschiedene Formen annehmen.

Funktionen mit Parametern

Auf eine Funktion wird zugegriffen, indem ihre Parameterwerte an den Hauptteil der Funktion übergeben werden. Wir können einzelne bis mehrere Parameterwerte als Tupel innerhalb der Funktion übergeben.

func mult(no1: Int, no2: Int) -> Int {
   return no1*no2
}

print(mult(no1: 2, no2: 20))
print(mult(no1: 3, no2: 15))
print(mult(no1: 4, no2: 30))

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

40
45
120

Funktionen ohne Parameter

Wir können auch Funktionen ohne Parameter haben.

Syntax

func funcname() -> datatype {
   return datatype
}

Es folgt ein Beispiel mit einer Funktion ohne Parameter -

func votersname() -> String {
   return "Alice"
}
print(votersname())

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

Alice

Funktionen mit Rückgabewerten

Funktionen werden auch verwendet, um String-, Integer- und Float-Datentypwerte als Rückgabetypen zurückzugeben. Um die größte und kleinste Zahl in einer bestimmten Array-Funktion herauszufinden, wird 'ls' mit großen und kleinen ganzzahligen Datentypen deklariert.

Ein Array wird initialisiert, um ganzzahlige Werte zu enthalten. Dann wird das Array verarbeitet und jeder einzelne Wert im Array wird gelesen und mit seinem vorherigen Wert verglichen. Wenn der Wert kleiner als der vorherige ist, wird er im Argument 'small' gespeichert, andernfalls wird er im Argument 'large' gespeichert und die Werte werden durch Aufrufen der Funktion zurückgegeben.

func ls(array: [Int]) -> (large: Int, small: Int) {
   var lar = array[0]
   var sma = array[0]

   for i in array[1..<array.count] {
      if i < sma {
         sma = i
      } else if i > lar {
         lar = i
      }
   }
   return (lar, sma)
}

let num = ls(array: [40,12,-5,78,98])
print("Largest number is: \(num.large) and smallest number is: \(num.small)")

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

Largest number is: 98 and smallest number is: -5

Funktionen ohne Rückgabewerte

Bei einigen Funktionen sind möglicherweise Argumente innerhalb der Funktion ohne Rückgabewerte deklariert. Das folgende Programm deklarierta und bals Argumente für die Funktion sum (). innerhalb der Funktion selbst die Werte für Argumentea und b werden durch Aufrufen des Funktionsaufrufs sum () übergeben und seine Werte werden gedruckt, wodurch Rückgabewerte eliminiert werden.

func sum(a: Int, b: Int) {
   let a = a + b
   let b = a - b
   print(a, b)
}

sum(a: 20, b: 10)
sum(a: 40, b: 10)
sum(a: 24, b: 6)

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

30 20
50 40
30 24

Funktionen mit optionalen Rückgabetypen

Swift 4 führt die optionale Funktion ein, um Probleme durch Einführung einer Sicherheitsmaßnahme zu beseitigen. Angenommen, wir deklarieren den Rückgabetyp für Funktionswerte als Ganzzahl, aber was passiert, wenn die Funktion einen Zeichenfolgenwert oder entweder einen Nullwert zurückgibt? In diesem Fall gibt der Compiler einen Fehlerwert zurück. 'optional' werden eingeführt, um diese Probleme zu beseitigen.

Optionale Funktionen haben zwei Formen: 'Wert' und 'Null'. Wir werden 'Optionals' mit dem reservierten Schlüsselzeichen '?' Erwähnen. um zu überprüfen, ob das Tupel einen Wert oder einen Nullwert zurückgibt.

func minMax(array: [Int]) -> (min: Int, max: Int)? {
   if array.isEmpty { return nil }
   var currentMin = array[0]
   var currentMax = array[0]
   
   for value in array[1..<array.count] {
      if value < currentMin {
         currentMin = value
      } else if value > currentMax {
         currentMax = value
      }
   }
   return (currentMin, currentMax)
}

if let bounds = minMax(array: [8, -6, 2, 109, 3, 71]) {
   print("min is \(bounds.min) and max is \(bounds.max)")
}

Wenn wir das obige Programm auf dem Spielplatz ausführen, erhalten wir folgendes Ergebnis:

min is -6 and max is 109

'' Optionale '' werden verwendet, um 'Null'- oder Garbage-Werte zu überprüfen, wodurch viel Zeit beim Debuggen verbraucht wird und der Code für den Benutzer effizient und lesbar wird.

Funktionen Local Vs External Parameternamen

Lokale Parameternamen

Auf lokale Parameternamen wird nur innerhalb der Funktion zugegriffen.

func sample(number: Int) {
   print(number)
}

Hier das funcDie Beispielargumentnummer wird als interne Variable deklariert, da die Funktion sample () intern auf sie zugreift. Hier wird die 'Zahl' als lokale Variable deklariert, aber der Verweis auf die Variable erfolgt außerhalb der Funktion mit der folgenden Anweisung:

func sample(number: Int) {
   print(number)
}

sample(number: 1)
sample(number: 2)
sample(number: 3)

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

1
2
3

Externe Parameternamen

Externe Parameternamen ermöglichen es uns, Funktionsparameter zu benennen, um ihren Zweck klarer zu machen. Zum Beispiel können Sie unten zwei Funktionsparameter benennen und diese Funktion dann wie folgt aufrufen:

func pow(firstArg a: Int, secondArg b: Int) -> Int {
   var res = a
   for _ in 1..<b {
      res = res * a
   }
   print(res)
   return res
}

pow(firstArg:5, secondArg:3)

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

125

Variadische Parameter

Wenn wir eine Funktion mit mehreren Argumenten definieren möchten, können wir die Elemente als 'variadische' Parameter deklarieren. Parameter können durch (···) nach dem Parameternamen als variadisch angegeben werden.

func vari<N>(members: N...){
   for i in members {
      print(i)
   }
}

vari(members: 4,3,5)
vari(members: 4.5, 3.1, 5.6)
vari(members: "Swift 4", "Enumerations", "Closures")

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

4
3
5
4.5
3.1
5.6
Swift 4
Enumerations
Closures

Konstante, Variable und E / A-Parameter

Funktionen betrachten die Parameter standardmäßig als 'konstant', während der Benutzer die Argumente für die Funktionen auch als Variablen deklarieren kann. Wir haben bereits besprochen, dass das Schlüsselwort 'let' verwendet wird, um konstante Parameter zu deklarieren, und variable Parameter mit dem Schlüsselwort 'var' definiert werden.

E / A-Parameter in Swift 4 bieten Funktionen zum Beibehalten der Parameterwerte, obwohl deren Werte nach dem Funktionsaufruf geändert werden. Zu Beginn der Funktionsparameterdefinition wird das Schlüsselwort 'inout' deklariert, um die Elementwerte beizubehalten.

Es leitet das Schlüsselwort 'inout' ab, da seine Werte 'in' an die Funktion übergeben werden und seine Werte von seinem Funktionskörper abgerufen und geändert werden, und es wird 'out' von der Funktion zurückgegeben, um das ursprüngliche Argument zu ändern.

Variablen werden nur als Argument für den In-Out-Parameter übergeben, da nur seine Werte innerhalb und außerhalb der Funktion geändert werden. Daher müssen Zeichenfolgen und Literale nicht als In-Out-Parameter deklariert werden. '&' vor einem Variablennamen verweist darauf, dass wir das Argument an den Parameter in-out übergeben.

func temp(a1: inout Int, b1: inout Int) {
   let t = a1
   a1 = b1
   b1 = t
}

var no = 2
var co = 10
temp(a1: &no, b1: &co)
print("Swapped values are \(no), \(co)")

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

Swapped values are 10, 2

Funktionstypen und ihre Verwendung

Jede Funktion folgt der spezifischen Funktion unter Berücksichtigung der Eingabeparameter und gibt das gewünschte Ergebnis aus.

func inputs(no1: Int, no2: Int) -> Int {
   return no1/no2
}

Das Folgende ist ein Beispiel -

func inputs(no1: Int, no2: Int) -> Int {
   return no1/no2
}

print(inputs(no1: 20, no2: 10))
print(inputs(no1: 36, no2: 6))

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

2
6

Hier wird die Funktion mit zwei Argumenten initialisiert no1 und no2 als ganzzahlige Datentypen und deren Rückgabetyp wird auch als 'int' deklariert.

Func inputstr(name: String) -> String {
   return name
}

Hier wird die Funktion als deklariert string Datentyp.

Funktionen können auch haben void Datentypen und solche Funktionen geben nichts zurück.

func inputstr() {
   print("Swift 4 Functions")
   print("Types and its Usage")
}
inputstr()

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

Swift 4 Functions
Types and its Usage

Die obige Funktion wird als void-Funktion ohne Argumente und ohne Rückgabewerte deklariert.

Funktionstypen verwenden

Funktionen werden zuerst mit Argumenten vom Typ Integer, Float oder String übergeben und dann wie unten erwähnt als Konstanten oder Variablen an die Funktion übergeben.

var addition: (Int, Int) -> Int = sum

Hier ist sum ein Funktionsname mit ganzzahligen Variablen 'a' und 'b', der jetzt als Variable zum Hinzufügen des Funktionsnamens deklariert wird. Im Folgenden haben sowohl die Additions- als auch die Summenfunktion die gleiche Anzahl von Argumenten, die als ganzzahliger Datentyp deklariert sind, und geben auch ganzzahlige Werte als Referenzen zurück.

func sum(a: Int, b: Int) -> Int {
   return a + b
}
var addition: (Int, Int) -> Int = sum
print("Result: \(addition(40, 89))")

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

Result: 129

Funktionstypen als Parametertypen und Rückgabetypen

Wir können die Funktion selbst auch als Parametertypen an eine andere Funktion übergeben.

func sum(a: Int, b: Int) -> Int {
   return a + b
}
var addition: (Int, Int) -> Int = sum
print("Result: \(addition(40, 89))")

func another(addition: (Int, Int) -> Int, a: Int, b: Int) {
   print("Result: \(addition(a, b))")
}
another(sum, 10, 20)

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

Result: 129
Result: 30

Verschachtelte Funktionen

Eine verschachtelte Funktion bietet die Möglichkeit, die äußere Funktion durch Aufrufen der inneren Funktion aufzurufen.

func calcDecrement(forDecrement total: Int) -> () -> Int {
   var overallDecrement = 0
   func decrementer() -> Int {
      overallDecrement -= total
      return overallDecrement
   }
   return decrementer
}

let decrem = calcDecrement(forDecrement: 30)
print(decrem())

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

-30

Closures in Swift 4 ähneln denen von in sich geschlossenen Funktionen, die als Blöcke organisiert sind und überall wie C- und Objective C-Sprachen aufgerufen werden. Innerhalb der Funktionen definierte Konstanten und Variablenreferenzen werden erfasst und in Abschlüssen gespeichert. Funktionen werden als Sonderfälle von Schließungen betrachtet und haben die folgenden drei Formen:

Globale Funktionen Verschachtelte Funktionen Abschlussausdrücke
Habe einen Namen. Erfassen Sie keine Werte Habe einen Namen. Erfassen Sie Werte aus der Umschließungsfunktion Unbenannte Abschlüsse erfassen Werte aus den benachbarten Blöcken

Abschlussausdrücke in der Sprache Swift 4 folgen gestochen scharfen, optimierten und leichtgewichtigen Syntaxstilen, einschließlich.

  • Ableiten von Parameter- und Rückgabewerttypen aus dem Kontext.
  • Implizite Rückgabe von Einzelausdrucksabschlüssen.
  • Kurzargumentnamen und
  • Syntax für nachfolgende Verschlüsse

Syntax

Es folgt eine generische Syntax zum Definieren des Abschlusses, die Parameter akzeptiert und einen Datentyp zurückgibt.

{
   (parameters) −> return type in
   statements
}

Das Folgende ist ein einfaches Beispiel -

let studname = { print("Welcome to Swift Closures") }
studname()

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

Welcome to Swift Closures

Der folgende Abschluss akzeptiert zwei Parameter und gibt einen Bool-Wert zurück -

{     
   (Int, Int) −> Bool in
   Statement1
   Statement 2
   ---
   Statement n
}

Das Folgende ist ein einfaches Beispiel -

let divide = {
   (val1: Int, val2: Int) -> Int in 
   return val1 / val2 
}

let result = divide(200, 20)
print (result)

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

10

Ausdrücke in Abschlüssen

Verschachtelte Funktionen bieten eine bequeme Möglichkeit, Codeblöcke zu benennen und zu definieren. Anstatt die gesamte Funktionsdeklaration darzustellen, werden Namenskonstrukte verwendet, um kürzere Funktionen zu kennzeichnen. Die Darstellung der Funktion in einer klaren kurzen Aussage mit fokussierter Syntax wird durch Abschlussausdrücke erreicht.

Programm für aufsteigende Bestellungen

Das Sortieren eines Strings wird durch die reservierte Swift 4s-Schlüsselfunktion "sortiert" erreicht, die bereits in der Standardbibliothek verfügbar ist. Die Funktion sortiert die angegebenen Zeichenfolgen in aufsteigender Reihenfolge und gibt die Elemente in einem neuen Array mit derselben Größe und demselben Datentyp zurück, die im alten Array erwähnt wurden. Das alte Array bleibt gleich.

Innerhalb der sortierten Funktion werden zwei Argumente dargestellt -

  • Werte bekannten Typs werden als Arrays dargestellt.

  • Array-Inhalt (Int, Int) und Rückgabe eines Booleschen Werts (Bool) Wenn das Array richtig sortiert ist, wird der Wert true zurückgegeben, andernfalls wird false zurückgegeben.

Eine normale Funktion mit Eingabezeichenfolge wird geschrieben und an die sortierte Funktion übergeben, um die Zeichenfolgen in ein neues Array zu sortieren, das unten gezeigt wird -

func ascend(s1: String, s2: String) -> Bool {
   return s1 > s2
}

let stringcmp = ascend(s1: "Swift 4", s2: "great")
print (stringcmp)

Wenn wir das obige Programm auf dem Spielplatz ausführen, erhalten wir folgendes Ergebnis:

true

Das anfängliche Array, das für Eis sortiert werden soll, wird als "Swift 4" und "great" angegeben. Die Funktion zum Sortieren des Arrays wird als String-Datentyp deklariert und der Rückgabetyp als Boolean bezeichnet. Beide Zeichenfolgen werden in aufsteigender Reihenfolge verglichen und sortiert und in einem neuen Array gespeichert. Wenn die Sortierung erfolgreich durchgeführt wurde, gibt die Funktion einen wahren Wert zurück, andernfalls wird false zurückgegeben.

Die Syntax des Abschlussausdrucks verwendet -

  • konstante Parameter,
  • variable Parameter und
  • Inout-Parameter.

Der Abschlussausdruck unterstützte keine Standardwerte. Variadische Parameter und Tupel können auch als Parametertypen und Rückgabetypen verwendet werden.

let sum = {
   (no1: Int, no2: Int) -> Int in 
   return no1 + no2 
}

let digits = sum(10, 20)
print(digits)

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

30

Die in der Funktionsanweisung genannten Parameter und Rückgabetypdeklarationen können auch durch die Inline-Closure-Ausdrucksfunktion mit dem Schlüsselwort 'in' dargestellt werden. Nach dem Deklarieren von Parametern und Rückgabetypen wird das Schlüsselwort 'in' verwendet, um den Hauptteil des Abschlusses anzuzeigen.

Implizite Rückgabe einzelner Ausdrücke

Hier macht der Funktionstyp des zweiten Arguments der sortierten Funktion deutlich, dass ein Bool-Wert vom Abschluss zurückgegeben werden muss. Da der Textkörper des Abschlusses einen einzelnen Ausdruck (s1> s2) enthält, der einen Bool-Wert zurückgibt, besteht keine Mehrdeutigkeit, und das Schlüsselwort return kann weggelassen werden.

Um eine einzelne Ausdrucksanweisung in Ausdrucksschließungen zurückzugeben, wird das Schlüsselwort 'return' in seinem Deklarationsteil weggelassen.

var count:[Int] = [5, 10, -6, 75, 20]
let descending = count.sorted(by: { n1, n2 in n1 > n2 })
let ascending = count.sorted(by: { n1, n2 in n1 < n2 })

print(descending)
print(ascending)

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

[75, 20, 10, 5, -6]
[-6, 5, 10, 20, 75]

Die Anweisung selbst definiert klar, dass wenn string1 größer als string 2 ist, true zurückgegeben wird, andernfalls false, daher wird die return-Anweisung hier weggelassen.

Bekannte Verschlüsse

Betrachten Sie die Addition von zwei Zahlen. Wir wissen, dass Addition den ganzzahligen Datentyp zurückgibt. Daher werden bekannte Typverschlüsse als - deklariert.

let sub = {
   (no1: Int, no2: Int) -> Int in 
   return no1 - no2 
}

let digits = sub(10, 20)
print(digits)

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

-10

Kurznamenargumentnamen als Abschluss deklarieren

Swift 4 stellt Inline-Abschlüssen automatisch Kurzargumentnamen zur Verfügung, mit denen auf die Werte der Argumente des Abschlusses mit den Namen $ 0 verwiesen werden kann. $1, $2 und so weiter.

var shorthand: (String, String) -> String
shorthand = { $1 }
print(shorthand("100", "200"))

Hier beziehen sich $ 0 und $ 1 auf das erste und zweite String-Argument des Abschlusses.

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

200

Swift 4 erleichtert dem Benutzer die Darstellung von Inline-Abschlüssen als Kurzargumentnamen, indem $ 0 dargestellt wird. $1, $2 --- $ n.

Die Liste der Closures-Argumente wird im Definitionsabschnitt weggelassen, wenn wir Kurzargumentnamen in Closure-Ausdrücken darstellen. Basierend auf dem Funktionstyp werden die Kurzargumentnamen abgeleitet. Da das Kurzargument im Ausdruckskörper definiert ist, wird das Schlüsselwort 'in' weggelassen.

Verschlüsse als Bedienerfunktionen

Swift 4 bietet eine einfache Möglichkeit, auf die Mitglieder zuzugreifen, indem lediglich Bedienerfunktionen als Verschlüsse bereitgestellt werden. In den vorherigen Beispielen wird das Schlüsselwort 'Bool' verwendet, um entweder 'true' zurückzugeben, wenn die Zeichenfolgen gleich sind, andernfalls wird 'false' zurückgegeben.

Der Ausdruck wird durch die Operatorfunktion beim Schließen noch einfacher als -

let numb = [98, -20, -30, 42, 18, 35]
var sortedNumbers = numb.sorted ({
   (left: Int, right: Int) -> Bool in
   return left < right
})

let asc = numb.sorted(<)
print(asc)

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

[-30, -20, 18, 35, 42, 98]

Verschlüsse als Anhänger

Das Übergeben des letzten Arguments der Funktion an einen Abschlussausdruck wird mit Hilfe von 'Trailing Closures' deklariert. Es wird außerhalb der Funktion () mit {} geschrieben. Die Verwendung ist erforderlich, wenn die Funktion nicht in einer einzelnen Zeile inline geschrieben werden kann.

reversed = sorted(names) { $0 > $1}

Dabei werden {$ 0> $ 1} als nach außen deklarierte abschließende Verschlüsse (Namen) dargestellt.

import Foundation
var letters = ["North", "East", "West", "South"]

let twoletters = letters.map({ 
   (state: String) -> String in
   return state.substringToIndex(advance(state.startIndex, 2)).uppercaseString
})

let stletters = letters.map() { 
   $0.substringToIndex(advance($0.startIndex, 2)).uppercaseString 
}
print(stletters)

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

[NO, EA, WE, SO]

Erfassen von Werten und Referenztypen

In Swift 4 erfolgt die Erfassung von Konstanten- und Variablenwerten mithilfe von Abschlüssen. Außerdem werden die Werte für diese Konstanten und Variablen im Abschlusskörper referenziert und geändert, obwohl die Variablen nicht mehr vorhanden sind.

Das Erfassen von konstanten und variablen Werten wird erreicht, indem verschachtelte Funktionen verwendet werden, indem Funktionen mit in den Körper anderer Funktionen geschrieben werden.

Eine verschachtelte Funktion erfasst -

  • Äußere Funktionsargumente.
  • Erfassen Sie Konstanten und Variablen, die in der Funktion Außen definiert sind.

Wenn in Swift 4 eine Konstante oder eine Variable innerhalb einer Funktion deklariert wird, wird durch das Schließen automatisch ein Verweis auf diese Variablen erstellt. Es bietet auch die Möglichkeit, mehr als zwei Variablen als denselben Abschluss wie folgt zu bezeichnen:

let decrem = calcDecrement(forDecrement: 18)
decrem()

Hier oneDecrement und Decrement-Variablen zeigen beide auf denselben Speicherblock als Abschlussreferenz.

func calcDecrement(forDecrement total: Int) -> () -> Int {
   var overallDecrement = 100
   func decrementer() -> Int {
      overallDecrement -= total
      print(overallDecrement)
      return overallDecrement
   }
   return decrementer
}

let decrem = calcDecrement(forDecrement: 18)
decrem()
decrem()
decrem()

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

82
64
46

Wenn die äußere Funktion calcDecrement jedes Mal aufgerufen wird, ruft sie die Funktion decrementer () auf, dekrementiert den Wert um 18 und gibt das Ergebnis mit Hilfe der äußeren Funktion calcDecrement zurück. Hier wirkt calcDecrement als Abschluss.

Obwohl die Funktion decrementer () keine Argumente hat, bezieht sich das Schließen standardmäßig auf die Variablen 'OverallDecrement' und 'Total', indem die vorhandenen Werte erfasst werden. Die Kopie der Werte für die angegebenen Variablen wird mit der neuen Funktion decrementer () gespeichert. Swift 4 verwaltet Speicherverwaltungsfunktionen, indem Speicherplätze zugewiesen und freigegeben werden, wenn die Variablen nicht verwendet werden.

Eine Aufzählung ist ein benutzerdefinierter Datentyp, der aus einer Reihe zusammengehöriger Werte besteht. Stichwortenum wird verwendet, um den aufgezählten Datentyp zu definieren.

Aufzählungsfunktionalität

Die Aufzählung in Swift 4 ähnelt auch der Struktur von C und Ziel C.

  • Es wird in einer Klasse deklariert und auf seine Werte wird über die Instanz dieser Klasse zugegriffen.

  • Der anfängliche Elementwert wird mithilfe von Enum-Intializierern definiert.

  • Die Funktionalität wird auch durch die Sicherstellung der Standardprotokollfunktionalität erweitert.

Syntax

Aufzählungen werden mit dem Schlüsselwort enum eingeführt und setzen ihre gesamte Definition in geschweifte Klammern.

enum enumname {
   // enumeration values are described here
}

Beispielsweise können Sie eine Aufzählung für Wochentage wie folgt definieren:

enum DaysofaWeek {
   case Sunday
   case Monday
   ---
   case Saturday
}

Beispiel

enum names {
   case Swift
   case Closures
}

var lang = names.Closures
lang = .Closures

switch lang {
   case .Swift:
      print("Welcome to Swift")
   case .Closures:
      print("Welcome to Closures")
   default:
      print("Introduction")
}

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

Welcome to Closures

Die Swift 4-Aufzählung weist ihren Mitgliedern keinen Standardwert wie C und Ziel C zu. Stattdessen werden die Mitglieder explizit durch ihre Aufzählungsnamen definiert. Der Name der Aufzählung sollte mit einem Großbuchstaben beginnen (Beispiel: enum DaysofaWeek).

var weekDay = DaysofaWeek.Sunday

Hier wird der Aufzählungsname 'DaysofaWeek' einem variablen Wochentag zugewiesen. Sonntag. Es informiert den Compiler, dass der Datentyp, der zum Sonntag gehört, nachfolgenden Enum-Mitgliedern dieser bestimmten Klasse zugewiesen wird. Sobald der Datentyp enum member definiert ist, kann auf die Mitglieder zugegriffen werden, indem Werte übergeben und weitere Berechnungen durchgeführt werden.

Aufzählung mit Switch-Anweisung

Die Swift 4-Anweisung 'Switch' folgt ebenfalls der Mehrwegauswahl. Auf eine Variable wird zu einem bestimmten Zeitpunkt basierend auf der angegebenen Bedingung zugegriffen. Der Standardfall in der switch-Anweisung wird verwendet, um nicht angegebene Fälle abzufangen.

enum Climate {
   case India
   case America
   case Africa
   case Australia
}

var season = Climate.America
season = .America
switch season {
   case .India:
      print("Climate is Hot")
   case .America:
      print("Climate is Cold")
   case .Africa:
      print("Climate is Moderate")
   case .Australia:
      print("Climate is Rainy")
   
}

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

Climate is Cold

Das Programm definiert zunächst Climate als Aufzählungsnamen. Dann werden seine Mitglieder wie "Indien", "Amerika", "Afrika" und "Australien" zur Klasse "Klima" erklärt. Jetzt ist das Mitglied Amerika einer Saisonvariablen zugeordnet. Außerdem werden in Switch case die Werte angezeigt, die .America entsprechen, und es wird zu dieser bestimmten Anweisung verzweigt. Die Ausgabe wird als "Klima ist kalt" angezeigt. Ebenso kann auf alle Mitglieder über switch-Anweisungen zugegriffen werden. Wenn die Bedingung nicht erfüllt ist, wird standardmäßig "Klima ist nicht vorhersehbar" gedruckt.

Die Aufzählung kann weiter in zugehörige Werte und Rohwerte unterteilt werden.

Unterschied zwischen zugehörigen Werten und Rohwerten

Zugehörige Werte Rohwerte
Verschiedene Datentypen Gleiche Datentypen
Beispiel: enum {10,0.8, "Hallo"} Beispiel: Aufzählung {10,35,50}
Werte werden basierend auf Konstanten oder Variablen erstellt Vorbevölkerte Werte
Variiert jedes Mal, wenn es deklariert wird Der Wert für das Mitglied ist der gleiche

Aufzählung mit zugehörigen Werten

enum Student {
   case Name(String)
   case Mark(Int,Int,Int)
}

var studDetails = Student.Name("Swift 4")
var studMarks = Student.Mark(98,97,95)

switch studMarks {
   case .Name(let studName):
      print("Student name is: \(studName).")
   case .Mark(let Mark1, let Mark2, let Mark3):
      print("Student Marks are: \(Mark1),\(Mark2),\(Mark3).")
}

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

Student Marks are: 98,97,95.

Betrachten Sie zum Beispiel den Zugriff auf den Schülernamen und die in drei Fächern gesicherten Noten. Der Aufzählungsname wird als Schüler deklariert, und die in der Aufzählungsklasse vorhandenen Mitglieder sind Namen, die zum Zeichenfolgendatentyp gehören. Noten werden als Marke1, Marke2 und Marke3 des Datentyps Integer dargestellt. Zugriff auf den Namen des Schülers oder auf die von ihm erzielten Noten

var studDetails = Student.Name("Swift")
var studMarks = Student.Mark(98,97,95)

Jetzt druckt der Switch-Fall den Schülernamen, wenn dieser Fallblock ausgeführt wird, andernfalls werden die vom Schüler gesicherten Markierungen gedruckt. Wenn beide Bedingungen fehlschlagen, wird der Standardblock ausgeführt.

Aufzählung mit Rohwerten

Rohwerte können Zeichenfolgen, Zeichen oder beliebige Ganzzahl- oder Gleitkommazahlentypen sein. Jeder Rohwert muss innerhalb seiner Aufzählungsdeklaration eindeutig sein. Wenn Ganzzahlen für Rohwerte verwendet werden, werden sie automatisch erhöht, wenn für einige der Aufzählungselemente kein Wert angegeben wird.

enum Month: Int {
   case January = 1, February, March, April, May, June, July, August,
      September, October, November, December
}

let yearMonth = Month.May.rawValue
print("Value of the Month is: \(yearMonth).")

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

Value of the Month is: 5.

Swift 4 bietet einen flexiblen Baustein für die Verwendung von Konstrukten als Strukturen. Durch einmaliges Verwenden dieser Strukturen können Konstruktmethoden und -eigenschaften definiert werden.

Im Gegensatz zu C und Ziel C.

  • Für die Struktur müssen keine Implementierungsdateien und keine Schnittstelle erforderlich sein.

  • Struktur ermöglicht es uns, eine einzelne Datei zu erstellen und ihre Schnittstelle automatisch auf andere Blöcke zu erweitern.

In Structure werden die Variablenwerte kopiert und in nachfolgenden Codes übergeben, indem eine Kopie der alten Werte zurückgegeben wird, sodass die Werte nicht geändert werden können.

Syntax

Structures are defined with a 'Struct' Keyword.
struct nameStruct {
   Definition 1
   Definition 2
   ---
   Definition N
}

Definition einer Struktur

Nehmen wir zum Beispiel an, wir müssen auf den Schülerdatensatz zugreifen, der Noten von drei Fächern enthält, und die Summe von drei Fächern herausfinden. Hier wird markStruct verwendet, um eine Struktur mit drei Markierungen als Datentyp 'Int' zu initialisieren.

struct MarkStruct {
   var mark1: Int
   var mark2: Int
   var mark3: Int
}

Zugriff auf die Struktur und ihre Eigenschaften

Auf die Mitglieder der Struktur wird über ihren Strukturnamen zugegriffen. Die Instanzen der Struktur werden mit dem Schlüsselwort 'let' initialisiert.

struct studentMarks {
   var mark1 = 100
   var mark2 = 200
   var mark3 = 300
}

let marks = studentMarks()
print("Mark1 is \(marks.mark1)")
print("Mark2 is \(marks.mark2)")
print("Mark3 is \(marks.mark3)")

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

Mark1 is 100
Mark2 is 200
Mark3 is 300

Auf die Noten der Schüler wird über den Strukturnamen 'studentMarks' zugegriffen. Die Strukturelemente werden als mark1, mark2, mark3 mit ganzzahligen Typwerten initialisiert. Dann wird die Struktur studentMarks () mit dem Schlüsselwort 'let' an die 'Marks' übergeben. Im Folgenden enthalten 'Marken' die Strukturelementwerte. Jetzt werden die Werte gedruckt, indem mit '.' Auf die Strukturelementwerte zugegriffen wird. mit seinen initialisierten Namen.

struct MarksStruct {
   var mark: Int

   init(mark: Int) {
      self.mark = mark
   }
}

var aStruct = MarksStruct(mark: 98)
var bStruct = aStruct     // aStruct and bStruct are two structs with the same value!
bStruct.mark = 97

print(aStruct.mark)      // 98
print(bStruct.mark)      // 97

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

98
97

Best Usage Practices von Strukturen

Die Sprache Swift 4 bietet die Funktionalität, Strukturen als benutzerdefinierte Datentypen zum Erstellen der Funktionsblöcke zu definieren. Die Instanzen der Struktur werden zur weiteren Bearbeitung durch ihren Wert an die definierten Blöcke übergeben.

Notwendigkeit, Strukturen zu haben

  • Einfache Datenwerte kapseln.

  • Kopieren der gekapselten Daten und der zugehörigen Eigenschaften nach "Werten" und nicht nach "Referenzen".

  • Struktur zum 'Kopieren' und 'Referenz'.

Strukturen in Swift 4 übergeben ihre Mitglieder mit ihren Werten und nicht mit ihren Referenzen.

struct markStruct {
   var mark1: Int
   var mark2: Int
   var mark3: Int

   init(mark1: Int, mark2: Int, mark3: Int) {
      self.mark1 = mark1
      self.mark2 = mark2
      self.mark3 = mark3
   }
}

var marks = markStruct(mark1: 98, mark2: 96, mark3:100)
print(marks.mark1)
print(marks.mark2)
print(marks.mark3)

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

98
96
100

Ein anderes Beispiel

struct markStruct {
   var mark1: Int
   var mark2: Int
   var mark3: Int
   
   init(mark1: Int, mark2: Int, mark3: Int) {
      self.mark1 = mark1
      self.mark2 = mark2
      self.mark3 = mark3
   }
}

var fail = markStruct(mark1: 34, mark2: 42, mark3: 13)

print(fail.mark1)
print(fail.mark2)
print(fail.mark3)

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

34
42
13

Die Struktur 'markStruct' wird zuerst mit ihren Elementen mark1, mark2 und mark3 definiert. Jetzt werden die Variablen der Elementklassen so initialisiert, dass sie ganzzahlige Werte enthalten. Anschließend wird die Kopie der Strukturelemente mit dem Schlüsselwort 'self' erstellt. Sobald die Kopie der Strukturelemente erstellt wurde, wird der Strukturblock mit seinen Parametermarken an die Variable 'Marks' übergeben, die nun die Schülermarkierungen enthält. Dann werden die Markierungen als 98, 96, 100 gedruckt. Im nächsten Schritt für dieselben Strukturelemente wird eine andere Instanz mit dem Namen "Fehler" verwendet, um dieselben Strukturelemente mit unterschiedlichen Markierungen zu kennzeichnen. Dann werden die Ergebnisse jetzt als 34, 42, 13 gedruckt. Dies erklärt deutlich, dass Strukturen eine Kopie der Elementvariablen haben und die Elemente dann an ihre kommenden Funktionsblöcke übergeben.

Klassen in Swift 4 sind Bausteine ​​flexibler Konstrukte. Ähnlich wie bei Konstanten, Variablen und Funktionen kann der Benutzer Klasseneigenschaften und -methoden definieren. Swift 4 bietet uns die Funktionalität, dass die Benutzer beim Deklarieren von Klassen keine Schnittstellen oder Implementierungsdateien erstellen müssen. Mit Swift 4 können wir Klassen als einzelne Datei erstellen. Die externen Schnittstellen werden standardmäßig erstellt, sobald die Klassen initialisiert sind.

Vorteile von Klassen

  • Durch Vererbung werden die Eigenschaften einer Klasse an eine andere Klasse übertragen

  • Mit Type Casting kann der Benutzer den Klassentyp zur Laufzeit überprüfen

  • Deinitializer sorgen für die Freigabe von Speicherressourcen

  • Durch die Referenzzählung kann die Klasseninstanz mehr als eine Referenz haben

Gemeinsame Merkmale von Klassen und Strukturen

  • Eigenschaften werden zum Speichern von Werten definiert
  • Indizes werden für den Zugriff auf Werte definiert
  • Methoden werden initialisiert, um die Funktionalität zu verbessern
  • Der Anfangszustand wird durch Initialisierer definiert
  • Die Funktionen werden über die Standardwerte hinaus erweitert
  • Bestätigen von Protokollfunktionsstandards

Syntax

Class classname {
   Definition 1
   Definition 2
   --- 
   Definition N
}

Klassendefinition

class student {
   var studname: String
   var mark: Int 
   var mark2: Int 
}

Die Syntax zum Erstellen von Instanzen

let studrecord = student()

Beispiel

class MarksStruct {
   var mark: Int
   init(mark: Int) {
      self.mark = mark
   }
}

class studentMarks {
   var mark = 300
}

let marks = studentMarks()
print("Mark is \(marks.mark)")

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

Mark is 300

Zugriff auf Klasseneigenschaften als Referenztypen

Auf Klasseneigenschaften kann mit dem '.' Syntax. Der Eigenschaftsname wird durch ein '.' Getrennt. nach dem Instanznamen.

class MarksStruct {
   var mark: Int
   init(mark: Int) {
      self.mark = mark
   }
}

class studentMarks {
   var mark1 = 300
   var mark2 = 400
   var mark3 = 900
}

let marks = studentMarks()
print("Mark1 is \(marks.mark1)")
print("Mark2 is \(marks.mark2)")
print("Mark3 is \(marks.mark3)")

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

Mark1 is 300
Mark2 is 400
Mark3 is 900

Klassenidentitätsoperatoren

Klassen in Swift 4 verweisen auf mehrere Konstanten und Variablen, die auf eine einzelne Instanz verweisen. Um zu wissen, welche Konstanten und Variablen auf eine bestimmte Klasseninstanz verweisen, werden Identitätsoperatoren verwendet. Klasseninstanzen werden immer als Referenz übergeben. In den Klassen werden NSString-, NSArray- und NSDictionary-Instanzen immer als Referenz auf eine vorhandene Instanz und nicht als Kopie zugewiesen und weitergegeben.

Identisch mit den Betreibern Nicht identisch mit Betreibern
Der verwendete Operator ist (===) Der verwendete Operator ist (! ==)
Gibt true zurück, wenn zwei Konstanten oder Variablen auf dieselbe Instanz verweisen Gibt true zurück, wenn zwei Konstanten oder Variablen auf eine andere Instanz verweisen
class SampleClass: Equatable {
   let myProperty: String
   init(s: String) {
      myProperty = s
   }
}

func ==(lhs: SampleClass, rhs: SampleClass) -> Bool {
   return lhs.myProperty == rhs.myProperty
}

let spClass1 = SampleClass(s: "Hello")
let spClass2 = SampleClass(s: "Hello")

spClass1 === spClass2 // false
print("\(spClass1)")

spClass1 !== spClass2 // true
print("\(spClass2)")

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

main.SampleClass
main.SampleClass

Die Sprache Swift 4 bietet Eigenschaften für Klasse, Aufzählung oder Struktur, um Werte zuzuordnen. Eigenschaften können weiter in gespeicherte Eigenschaften und berechnete Eigenschaften klassifiziert werden.

Unterschied zwischen gespeicherten und berechneten Eigenschaften

Gespeichertes Eigentum Berechnete Eigenschaft
Speichern Sie konstante und variable Werte als Instanz Berechnen Sie einen Wert, anstatt den Wert zu speichern
Bereitgestellt von Klassen und Strukturen Bereitgestellt durch Klassen, Aufzählungen und Strukturen

Sowohl gespeicherte als auch berechnete Eigenschaften sind dem Instanztyp zugeordnet. Wenn die Eigenschaften mit ihren Typwerten verknüpft sind, wird sie als "Typeneigenschaften" definiert. Gespeicherte und berechnete Eigenschaften sind normalerweise Instanzen eines bestimmten Typs zugeordnet. Eigenschaften können jedoch auch dem Typ selbst zugeordnet werden. Solche Eigenschaften sind als Typeneigenschaften bekannt. Immobilienbeobachter werden ebenfalls eingesetzt

  • Um den Wert der gespeicherten Eigenschaften zu beobachten
  • Beobachtung der Eigenschaft der von der Oberklasse abgeleiteten geerbten Unterklasse

Gespeicherte Eigenschaften

Swift 4 führt das Konzept der gespeicherten Eigenschaften ein, um die Instanzen von Konstanten und Variablen zu speichern. Gespeicherte Eigenschaften von Konstanten werden durch das Schlüsselwort 'let' definiert, und gespeicherte Eigenschaften von Variablen werden durch das Schlüsselwort 'var' definiert.

  • Während der Definition Die gespeicherte Eigenschaft liefert den Standardwert.
  • Während der Initialisierung kann der Benutzer die Anfangswerte initialisieren und ändern
struct Number {
   var digits: Int
   let pi = 3.1415
}

var n = Number(digits: 12345)
n.digits = 67

print("\(n.digits)")
print("\(n.pi)")

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

67
3.1415

Betrachten Sie die folgende Zeile im obigen Code -

let pi = 3.1415

Hier wird die Variable pi als gespeicherter Eigenschaftswert mit der Instanz pi = 3.1415 initialisiert. Wenn also die Instanz verwiesen wird, enthält sie nur den Wert 3.1415.

Eine andere Methode, um gespeicherte Eigenschaften zu haben, besteht darin, konstante Strukturen zu haben. Daher wird die gesamte Instanz der Strukturen als "gespeicherte Eigenschaften von Konstanten" betrachtet.

struct Number {
   var digits: Int
   let numbers = 3.1415
}

var n = Number(digits: 12345)
n.digits = 67

print("\(n.digits)")
print("\(n.numbers)")
n.numbers = 8.7

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

error: cannot assign to 'numbers' in 'n'
n.numbers = 8.7

Anstatt die 'Nummer' auf 8.7 neu zu initialisieren, wird eine Fehlermeldung zurückgegeben, die angibt, dass die 'Nummer' als konstant deklariert ist.

Lazy Stored Property

Swift 4 bietet eine flexible Eigenschaft namens "Lazy Stored Property", bei der die Anfangswerte nicht berechnet werden, wenn die Variable zum ersten Mal initialisiert wird. Der Modifikator 'faul' wird vor der Variablendeklaration verwendet, um ihn als faul gespeicherte Eigenschaft zu haben.

Lazy Properties werden verwendet -

  • Um die Objekterstellung zu verzögern.
  • Wenn die Eigenschaft von anderen Teilen einer Klasse abhängig ist, sind diese noch nicht bekannt
class sample {
   lazy var no = number()    // `var` declaration is required.
}

class number {
   var name = "Swift 4"
}

var firstsample = sample()
print(firstsample.no.name)

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

Swift 4

Instanzvariablen

In Ziel C verfügen gespeicherte Eigenschaften auch über Instanzvariablen zu Sicherungszwecken, um die in gespeicherten Eigenschaften deklarierten Werte zu speichern.

Swift 4 integriert diese beiden Konzepte in eine einzige Deklaration für gespeicherte Eigenschaften. Anstatt eine entsprechende Instanzvariable und einen Sicherungswert zu haben, enthält 'gespeicherte Eigenschaft' alle integrierten Informationen, die an einem einzigen Ort über die Variableneigenschaft nach Variablenname, Datentyp und Speicherverwaltungsfunktionen definiert sind.

Berechnete Eigenschaften

Anstatt die berechneten Werte zu speichern, stellen Sie einen Getter und einen optionalen Setter bereit, um andere Eigenschaften und Werte indirekt abzurufen und festzulegen.

class sample {
   var no1 = 0.0, no2 = 0.0
   var length = 300.0, breadth = 150.0

   var middle: (Double, Double) {
      get {
         return (length / 2, breadth / 2)
      }
      
      set(axis){
         no1 = axis.0 - (length / 2)
         no2 = axis.1 - (breadth / 2)
      }
   }
}

var result = sample()
print(result.middle)
result.middle = (0.0, 10.0)

print(result.no1)
print(result.no2)

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

(150.0, 75.0)
-150.0
-65.0

Wenn eine berechnete Eigenschaft den neuen Wert als undefiniert belässt, wird der Standardwert für diese bestimmte Variable festgelegt.

Berechnete Eigenschaften als schreibgeschützte Eigenschaften

Eine schreibgeschützte Eigenschaft in einer berechneten Eigenschaft wird als eine Eigenschaft mit Getter, aber ohne Setter definiert. Es wird immer verwendet, um einen Wert zurückzugeben. Auf die Variablen wird weiter über ein '.' Syntax kann aber nicht auf einen anderen Wert gesetzt werden.

class film {
   var head = ""
   var duration = 0.0
   var metaInfo: [String:String] {
      return [
         "head": self.head,
         "duration":"\(self.duration)"
      ]
   }
}

var movie = film()
movie.head = "Swift 4 Properties"
movie.duration = 3.09

print(movie.metaInfo["head"]!)
print(movie.metaInfo["duration"]!)

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

Swift 4 Properties
3.09

Berechnete Eigenschaften als Eigenschaftsbeobachter

In Swift 4 werden Eigenschaftsbeobachter verwendet, um Eigenschaftswerte zu beobachten und darauf zu reagieren. Jedes Mal, wenn Eigenschaftswerte festgelegt werden, werden Eigenschaftsbeobachter aufgerufen. Mit Ausnahme von verzögert gespeicherten Eigenschaften können wir der 'geerbten' Eigenschaft durch die Methode 'Überschreiben' Eigenschaftsbeobachter hinzufügen.

Eigenschaftsbeobachter können entweder definiert werden

  • Vor dem Speichern des Wertes - willset

  • Nach dem Speichern des neuen Wertes - didset

  • Wenn eine Eigenschaft in einem Initialisierer festgelegt wird, können Willens- und Didset-Beobachter nicht aufgerufen werden.

class Samplepgm {
   var counter: Int = 0 {
      willSet(newTotal){
         print("Total Counter is: \(newTotal)")
      }
      
      didSet {
         if counter > oldValue {
            print("Newly Added Counter \(counter - oldValue)")
         }
      }
   }
}

let NewCounter = Samplepgm()
NewCounter.counter = 100
NewCounter.counter = 800

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

Total Counter is: 100
Newly Added Counter 100
Total Counter is: 800
Newly Added Counter 700

Lokale und globale Variablen

Lokale und globale Variablen werden zum Berechnen und Beobachten der Eigenschaften deklariert.

Lokale Variablen Globale Variablen
Variablen, die in einem Funktions-, Methoden- oder Abschlusskontext definiert sind. Variablen, die außerhalb des Funktions-, Methoden-, Abschluss- oder Typkontexts definiert sind.
Wird zum Speichern und Abrufen von Werten verwendet. Wird zum Speichern und Abrufen von Werten verwendet.
Gespeicherte Eigenschaften werden verwendet, um die Werte abzurufen und festzulegen. Gespeicherte Eigenschaften werden verwendet, um die Werte abzurufen und festzulegen.
Berechnete Eigenschaften werden ebenfalls verwendet. Berechnete Eigenschaften werden ebenfalls verwendet.

Typ Eigenschaften

Die Eigenschaften werden im Abschnitt Typdefinition mit geschweiften Klammern {} definiert, und der Umfang der Variablen wurde ebenfalls zuvor definiert. Zum Definieren von Typeneigenschaften für Werttypen wird das Schlüsselwort 'static' und für Klassentypen das Schlüsselwort 'class' verwendet.

Syntax

struct Structname {
   static var storedTypeProperty = " "
   static var computedTypeProperty: Int {
      // return an Int value here
   }
}

enum Enumname {
   static var storedTypeProperty = " "
   static var computedTypeProperty: Int {
      // return an Int value here
   }
}

class Classname {
   class var computedTypeProperty: Int {
      // return an Int value here
   }
}

Eigenschaften abfragen und einstellen

Genau wie Instanzeigenschaften werden Typeneigenschaften abgefragt und mit '.' Syntax nur für den Typ, anstatt auf die Instanz zu verweisen.

struct StudMarks {
   static let markCount = 97
   static var totalCount = 0
   
   var InternalMarks: Int = 0 {
      didSet {
         if InternalMarks > StudMarks.markCount {
            InternalMarks = StudMarks.markCount
         }
         if InternalMarks > StudMarks.totalCount {
            StudMarks.totalCount = InternalMarks
         }
      }
   }
}

var stud1Mark1 = StudMarks()
var stud1Mark2 = StudMarks()

stud1Mark1.InternalMarks = 98
print(stud1Mark1.InternalMarks)

stud1Mark2.InternalMarks = 87
print(stud1Mark2.InternalMarks)

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

97
87

In der Sprache Swift 4 werden Funktionen, die bestimmten Typen zugeordnet sind, als Methoden bezeichnet. In Ziel C werden Klassen zum Definieren von Methoden verwendet, während die Sprache Swift 4 dem Benutzer Flexibilität bietet, Methoden für Klassen, Strukturen und Aufzählungen zu haben.

Instanzmethoden

In der Sprache Swift 4 wird über die Instanzmethoden auf Klassen-, Struktur- und Aufzählungsinstanzen zugegriffen.

Instanzmethoden bieten Funktionalität

  • Zugriff auf und Ändern von Instanzeigenschaften
  • Funktionalität in Bezug auf den Bedarf der Instanz

Die Instanzmethode kann in die geschweiften Klammern {} geschrieben werden. Es hat impliziten Zugriff auf Methoden und Eigenschaften der Typinstanz. Wenn eine bestimmte Instanz des Typs aufgerufen wird, erhält sie Zugriff auf diese bestimmte Instanz.

Syntax

func funcname(Parameters) -> returntype {
   Statement1
   Statement2
   ---
   Statement N
   return parameters
}

Beispiel

class calculations {
   let a: Int
   let b: Int
   let res: Int

   init(a: Int, b: Int) {
      self.a = a
      self.b = b
      res = a + b
   }
   
   func tot(c: Int) -> Int {
      return res - c
   }
   
   func result() {
      print("Result is: \(tot(c: 20))")
      print("Result is: \(tot(c: 50))")
   }
}
let pri = calculations(a: 600, b: 300)
pri.result()

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

Result is: 880
Result is: 850

Klassenberechnungen definieren zwei Instanzmethoden -

  • init () fügt zwei Zahlen a und b hinzu und speichert sie im Ergebnis 'res'.
  • tot () wird verwendet, um das 'res' vom Übergeben des 'c'-Werts zu subtrahieren

Schließlich wird das Drucken der Berechnungsmethoden mit Werten für a und b aufgerufen. Auf Instanzmethoden wird mit '.' Punktsyntax

Lokale und externe Parameternamen

Swift 4-Funktionen beschreiben sowohl lokale als auch globale Deklarationen für ihre Variablen. In ähnlicher Weise ähneln die Namenskonventionen für Swift 4-Methoden auch denen für Ziel C. Die Merkmale lokaler und globaler Parameternamendeklarationen unterscheiden sich jedoch für Funktionen und Methoden. Die ersten Parameter in Swift 4 werden durch Präpositionennamen als 'with', 'for' und 'by' bezeichnet, um den Zugriff auf Namenskonventionen zu erleichtern.

Swift 4 bietet Flexibilität bei Methoden, indem der erste Parametername als lokale Parameternamen und die verbleibenden Parameternamen als globale Parameternamen deklariert werden. Hier wird 'no1' von Swift 4-Methoden als lokale Parameternamen deklariert. 'no2' wird für globale Deklarationen verwendet und im gesamten Programm aufgerufen.

class division {
   var count: Int = 0
   func incrementBy(no1: Int, no2: Int) {
      count = no1 / no2
      print(count)
   }
}

let counter = division()
counter.incrementBy(no1: 1800, no2: 3)
counter.incrementBy(no1: 1600, no2: 5)
counter.incrementBy(no1: 11000, no2: 3)

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

600
320
3666

Externer Parametername mit # und _ Symbol

Obwohl Swift 4-Methoden erste Parameternamen für lokale Deklarationen bereitstellen, kann der Benutzer die Parameternamen von lokalen zu globalen Deklarationen ändern. Dies kann erreicht werden, indem dem ersten Parameternamen das Symbol '#' vorangestellt wird. Auf diese Weise kann in allen Modulen global auf den ersten Parameter zugegriffen werden.

Wenn der Benutzer mit einem externen Namen auf die nachfolgenden Parameternamen zugreifen muss, wird der Methodenname mithilfe des Symbols '_' überschrieben.

class multiplication {
   var count: Int = 0
   func incrementBy(no1: Int, no2: Int) {
      count = no1 * no2
      print(count)
   }
}

let counter = multiplication()

counter.incrementBy(no1: 800, no2: 3)
counter.incrementBy(no1: 100, no2: 5)
counter.incrementBy(no1: 15000, no2: 3)

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

2400
500
45000

Selbsteigenschaft in Methoden

Methoden haben eine implizite Eigenschaft, die als 'self' für alle definierten Typinstanzen bekannt ist. Die Eigenschaft 'Self' wird verwendet, um die aktuellen Instanzen für die definierten Methoden zu referenzieren.

class calculations {
   let a: Int
   let b: Int
   let res: Int

   init(a: Int, b: Int) {
      self.a = a
      self.b = b
      res = a + b
      print("Inside Self Block: \(res)")
   }
   
   func tot(c: Int) -> Int {
      return res - c
   }
   
   func result() {
      print("Result is: \(tot(c: 20))")
      print("Result is: \(tot(c: 50))")
   }
}

let pri = calculations(a: 600, b: 300)
let sum = calculations(a: 1200, b: 300)

pri.result()
sum.result()

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

Inside Self Block: 900
Inside Self Block: 1500
Result is: 880
Result is: 850
Result is: 1480
Result is: 1450

Ändern von Werttypen aus Instanzmethoden

In Swift 4 gehören Sprachstrukturen und Aufzählungen zu Werttypen, die mit ihren Instanzmethoden nicht geändert werden können. Die Sprache Swift 4 bietet jedoch Flexibilität, um die Werttypen durch "Mutieren" des Verhaltens zu ändern. Mutate nimmt alle Änderungen an den Instanzmethoden vor und kehrt nach Ausführung der Methode zum ursprünglichen Formular zurück. Außerdem wird durch die Eigenschaft 'self' eine neue Instanz für ihre implizite Funktion erstellt und ersetzt die vorhandene Methode nach ihrer Ausführung

struct area {
   var length = 1
   var breadth = 1
   
   func area() -> Int {
      return length * breadth
   }
   mutating func scaleBy(res: Int) {
      length *= res
      breadth *= res
      print(length)
      print(breadth)
   }
}

var val = area(length: 3, breadth: 5)
val.scaleBy(res: 3)
val.scaleBy(res: 30)
val.scaleBy(res: 300)

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

9
15
270
450
81000
135000

Selbsteigenschaft für Mutationsmethode

Mutierende Methoden in Kombination mit der Eigenschaft 'self' weisen der definierten Methode eine neue Instanz zu.

struct area {
   var length = 1
   var breadth = 1
   func area() -> Int {
      return length * breadth
   }
   mutating func scaleBy(res: Int) {
      self.length *= res
      self.breadth *= res
      print(length)
      print(breadth)
   }
}

var val = area(length: 3, breadth: 5)
val.scaleBy(res: 13)

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis. - -

39
65

Typ Methoden

Wenn eine bestimmte Instanz einer Methode aufgerufen wird, wird sie als Instanzmethode aufgerufen. und wenn die Methode einen bestimmten Typ einer Methode aufruft, wird sie als 'Typmethoden' bezeichnet. Typmethoden für 'Klassen' werden durch das Schlüsselwort 'func' definiert, und Strukturen und Aufzählungen Typmethoden werden mit dem Schlüsselwort 'static' vor dem Schlüsselwort 'func' definiert.

Typmethoden werden von '.' Aufgerufen und aufgerufen. Syntax, bei der anstelle des Aufrufs einer bestimmten Instanz die gesamte Methode aufgerufen wird.

class Math {
   class func abs(number: Int) -> Int {
      if number < 0 {
         return (-number)
      } else {
         return number
      }
   }
}

struct absno {
   static func abs(number: Int) -> Int {
      if number < 0 {
         return (-number)
      } else {
         return number
      }
   }
}

let no = Math.abs(number: -35)
let num = absno.abs(number: -5)

print(no)
print(num)

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis. - -

35
5

Der Zugriff auf die Elementelemente einer Sammlung, Sequenz und Liste in Klassen, Strukturen und Aufzählungen erfolgt mit Hilfe von Indizes. Diese Indizes werden zum Speichern und Abrufen der Werte mithilfe des Index verwendet. Auf Array-Elemente wird mit Hilfe von someArray [Index] zugegriffen, und auf die nachfolgenden Elementelemente in einer Dictionary-Instanz kann als someDicitonary [Schlüssel] zugegriffen werden.

Für einen einzelnen Typ können Indizes von einzelnen bis zu mehreren Deklarationen reichen. Wir können den entsprechenden Index verwenden, um den Typ des an den Index übergebenen Indexwerts zu überladen. Die Indizes reichen auch von einer Dimension bis zu mehreren Dimensionen, je nach den Anforderungen des Benutzers für seine Eingabedatentypdeklarationen.

Syntax der tiefgestellten Deklaration und ihre Verwendung

Lassen Sie uns einen Rückblick auf die berechneten Eigenschaften geben. Auch Indizes folgen der gleichen Syntax wie berechnete Eigenschaften. Bei der Abfrage von Typinstanzen werden Indizes in eine eckige Klammer gefolgt vom Instanznamen geschrieben. Die tiefgestellte Syntax folgt der gleichen Syntaxstruktur wie die Syntax 'Instanzmethode' und 'berechnete Eigenschaft'. Das Schlüsselwort 'subscript' wird zum Definieren von Indizes verwendet, und der Benutzer kann einzelne oder mehrere Parameter mit ihren Rückgabetypen angeben. Indizes können schreibgeschützte oder schreibgeschützte Eigenschaften haben, und die Instanzen werden mithilfe der Eigenschaften 'getter' und 'setter' wie die berechneten Eigenschaften gespeichert und abgerufen.

Syntax

subscript(index: Int) −> Int {
   get {
      // used for subscript value declarations
   }
   set(newValue) {
      // definitions are written here
   }
}

Beispiel 1

struct subexample {
   let decrementer: Int
   subscript(index: Int) -> Int {
      return decrementer / index
   }
}
let division = subexample(decrementer: 100)

print("The number is divisible by \(division[9]) times")
print("The number is divisible by \(division[2]) times")
print("The number is divisible by \(division[3]) times")
print("The number is divisible by \(division[5]) times")
print("The number is divisible by \(division[7]) times")

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

The number is divisible by 11 times
The number is divisible by 50 times
The number is divisible by 33 times
The number is divisible by 20 times
The number is divisible by 14 times

Beispiel2

class daysofaweek {
   private var days = ["Sunday", "Monday", "Tuesday", "Wednesday",
      "Thursday", "Friday", "saturday"]
   subscript(index: Int) -> String {
      get {
         return days[index]
      }
      set(newValue) {
         self.days[index] = newValue
      }
   }
}
var p = daysofaweek()

print(p[0])
print(p[1])
print(p[2])
print(p[3])

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

Sunday
Monday
Tuesday
Wednesday

Optionen im Index

Indizes verwenden einzelne bis mehrere Eingabeparameter, und diese Eingabeparameter gehören auch zu einem beliebigen Datentyp. Sie können auch variable und variable Parameter verwenden. Indizes können keine Standardparameterwerte bereitstellen oder In-Out-Parameter verwenden.

Das Definieren mehrerer Indizes wird als "Indexüberladung" bezeichnet, bei der eine Klasse oder Struktur nach Bedarf mehrere Indexdefinitionen bereitstellen kann. Diese mehreren Indizes werden basierend auf den Wertetypen abgeleitet, die in den Indexklammern deklariert sind.

struct Matrix {
   let rows: Int, columns: Int
   var print: [Double]
   init(rows: Int, columns: Int) {
      self.rows = rows
      self.columns = columns
      print = Array(count: rows * columns, repeatedValue: 0.0)
   }
   subscript(row: Int, column: Int) -> Double {
      get {
         return print[(row * columns) + column]
      }
      set {
         print[(row * columns) + column] = newValue
      }
   }
}
var mat = Matrix(rows: 3, columns: 3)

mat[0,0] = 1.0
mat[0,1] = 2.0
mat[1,0] = 3.0
mat[1,1] = 5.0

print("\(mat[0,0])")

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

1.0

Der Swift 4-Index unterstützt einzelne Parameter für mehrere Parameterdeklarationen für geeignete Datentypen. Das Programm deklariert die 'Matrix'-Struktur als 2 * 2-dimensionale Array-Matrix zum Speichern von' Double'-Datentypen. Der Matrix-Parameter wird mit Integer-Datentypen zum Deklarieren von Zeilen und Spalten eingegeben.

Eine neue Instanz für die Matrix wird erstellt, indem die Anzahl der Zeilen und Spalten wie unten gezeigt an die Initialisierung übergeben wird.

var mat = Matrix(rows: 3, columns: 3)

Matrixwerte können definiert werden, indem Zeilen- und Spaltenwerte in den Index übergeben werden, die wie unten gezeigt durch ein Komma getrennt sind.

mat[0,0] = 1.0  
mat[0,1] = 2.0
mat[1,0] = 3.0
mat[1,1] = 5.0

Die Fähigkeit, mehr als Form anzunehmen, wird als Vererbung definiert. Im Allgemeinen kann eine Klasse Methoden, Eigenschaften und Funktionen von einer anderen Klasse erben. Klassen können weiter in Unterklassen und Superklassen eingeteilt werden.

  • Sub Class - Wenn eine Klasse Eigenschaften, Methoden und Funktionen von einer anderen Klasse erbt, wird sie als Unterklasse bezeichnet

  • Super Class - Eine Klasse, die Eigenschaften, Methoden und Funktionen enthält, um andere Klassen von sich selbst zu erben, wird als Superklasse bezeichnet

Swift 4-Klassen enthalten eine Oberklasse, die Methoden, Eigenschaften, Funktionen und überschreibende Methoden aufruft und darauf zugreift. Außerdem werden Eigenschaftsbeobachter verwendet, um eine Eigenschaft hinzuzufügen und die gespeicherten oder berechneten Eigenschaftsmethoden zu ändern.

Basisklasse

Eine Klasse, die keine Methoden, Eigenschaften oder Funktionen von einer anderen Klasse erbt, wird als 'Basisklasse' bezeichnet.

class StudDetails {
   var stname: String!
   var mark1: Int!
   var mark2: Int!
   var mark3: Int!
   
   init(stname: String, mark1: Int, mark2: Int, mark3: Int) {
      self.stname = stname
      self.mark1 = mark1
      self.mark2 = mark2
      self.mark3 = mark3
   }
}

let stname = "Swift 4"
let mark1 = 98
let mark2 = 89
let mark3 = 76

print(stname)
print(mark1)
print(mark2)
print(mark3)

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

Swift 4
98
89
76

Klasse mit Klassennamen StudDetails werden hier als Basisklasse definiert, die den Schülernamen enthält, und drei Fächer werden als mark1, mark2 und mark3 markiert. Das Schlüsselwort 'let' wird verwendet, um den Wert für die Basisklasse zu initialisieren, und der Wert der Basisklasse wird mithilfe der Funktion 'print' auf dem Spielplatz angezeigt.

Unterklasse

Das Basieren einer neuen Klasse auf einer vorhandenen Klasse wird als "Unterklasse" definiert. Die Unterklasse erbt die Eigenschaften, Methoden und Funktionen ihrer Basisklasse. Zum Definieren einer Unterklasse wird ':' vor dem Namen der Basisklasse verwendet

class StudDetails {
   var mark1: Int;
   var mark2: Int;
   
   init(stm1:Int, results stm2:Int) {
      mark1 = stm1;
      mark2 = stm2;
   }
   func print() {
      print("Mark1:\(mark1), Mark2:\(mark2)")
   }
}

class display : StudDetails {
   init() {
      super.init(stm1: 93, results: 89)
   }
}

let marksobtained = display()
marksobtained.print()

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

Mark1:93, Mark2:89

Die Klasse 'StudDetails' ist als Superklasse definiert, in der Schülermarken deklariert werden und die Unterklasse 'display' verwendet wird, um die Noten von ihrer Superklasse zu erben. Die Unterklasse definiert die Schülerzeichen und ruft die print () -Methode auf, um die Schülerzeichen anzuzeigen.

Überschreiben

Der Zugriff auf die Unterklasse Superklasse Instanz, Typ Methoden, Instanz, Typ Eigenschaften und Indizes bietet das Konzept des Überschreibens. Das Schlüsselwort 'override' wird verwendet, um die in der Oberklasse deklarierten Methoden zu überschreiben.

Zugriff auf Methoden, Eigenschaften und Indizes der Superklasse

Das Schlüsselwort 'super' wird als Präfix verwendet, um auf die in der Superklasse deklarierten Methoden, Eigenschaften und Indizes zuzugreifen

Überschreiben Zugriff auf Methoden, Eigenschaften und Indizes
Methoden super.somemethod ()
Eigenschaften super.someProperty ()
Indizes super [someIndex]

Methoden überschreiben

Geerbte Instanz- und Typmethoden können durch das Schlüsselwort 'override' für unsere in unserer Unterklasse definierten Methoden überschrieben werden. Hier wird print () in der Unterklasse überschrieben, um auf die in der Superklasse print () erwähnte type-Eigenschaft zuzugreifen. Außerdem wird eine neue Instanz der Cricket () - Superklasse als "Cricinstance" erstellt.

class cricket {
   func print() {
      print("Welcome to Swift 4 Super Class")
   }
}

class tennis: cricket {
   override func print() {
      print("Welcome to Swift 4 Sub Class")
   }
}

let cricinstance = cricket()
cricinstance.print()

let tennisinstance = tennis()
tennisinstance.print()

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

Welcome to Swift Super Class
Welcome to Swift Sub Class

Eigentumsüberschreibung

Sie können eine geerbte Instanz oder Klasseneigenschaft überschreiben, um Ihren eigenen benutzerdefinierten Getter und Setter für diese Eigenschaft bereitzustellen, oder Eigenschaftsbeobachter hinzufügen, damit die überschreibende Eigenschaft beobachten kann, wenn sich der zugrunde liegende Eigenschaftswert ändert.

Überschreiben von Property Gettern und Setzern

Mit Swift 4 kann der Benutzer einen benutzerdefinierten Getter und Setter bereitstellen, um die geerbte Eigenschaft zu überschreiben, unabhängig davon, ob es sich um eine gespeicherte oder eine berechnete Eigenschaft handelt. Die Unterklasse kennt den Namen und den Typ der geerbten Eigenschaft nicht. Daher ist es wichtig, dass der Benutzer in der Unterklasse den Namen und den Typ der in der Superklasse angegebenen überschreibenden Eigenschaft angibt.

Dies kann auf zwei Arten erfolgen:

  • Wenn Setter für das Überschreiben von Eigenschaften definiert ist, muss der Benutzer auch Getter definieren.

  • Wenn wir den geerbten Eigenschafts-Getter nicht ändern möchten, können wir den geerbten Wert einfach über die Syntax 'super.someProperty' an die Super-Klasse übergeben.

class Circle {
   var radius = 12.5
   var area: String {
      return "of rectangle for \(radius) "
   }
}

class Rectangle: Circle {
   var print = 7
   override var area: String {
      return super.area + " is now overridden as \(print)"
   }
}

let rect = Rectangle()
rect.radius = 25.0
rect.print = 3
print("Radius \(rect.area)")

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

Radius of rectangle for 25.0  is now overridden as 3

Überschreiben von Immobilienbeobachtern

Wenn für eine geerbte Eigenschaft eine neue Eigenschaft hinzugefügt werden muss, wird in Swift 4 das Konzept zum Überschreiben von Eigenschaften eingeführt. Dadurch wird der Benutzer benachrichtigt, wenn der Wert der geerbten Eigenschaft geändert wird. Das Überschreiben gilt jedoch nicht für geerbte konstante gespeicherte Eigenschaften und geerbte schreibgeschützte berechnete Eigenschaften.

class Circle {
   var radius = 12.5
   var area: String {
     return "of rectangle for \(radius) "
   }
}

class Rectangle: Circle {
   var print = 7
   override var area: String {
      return super.area + " is now overridden as \(print)"
   }
}

let rect = Rectangle()
rect.radius = 25.0
rect.print = 3
print("Radius \(rect.area)")

class Square: Rectangle {
   override var radius: Double {
      didSet {
         print = Int(radius/5.0)+1
      }
   }
}

let sq = Square()
sq.radius = 100.0
print("Radius \(sq.area)")

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

Radius of rectangle for 25.0  is now overridden as 3
Radius of rectangle for 100.0  is now overridden as 21

Letzte Eigenschaft, um ein Überschreiben zu verhindern

Wenn der Benutzer nicht möchte, dass andere auf Methoden, Eigenschaften oder Indizes der Superklasse zugreifen, führt Swift 4 die Eigenschaft 'final' ein, um ein Überschreiben zu verhindern. Sobald die Eigenschaft 'final' deklariert ist, können die Methoden, Eigenschaften und Indizes der Superklasse durch die Indizes nicht mehr überschrieben werden. Es ist nicht vorgesehen, eine "endgültige" Eigenschaft in einer "Superklasse" zu haben. Wenn die Eigenschaft 'final' deklariert wird, darf der Benutzer keine weiteren Unterklassen erstellen.

final class Circle {
   final var radius = 12.5
   var area: String {
      return "of rectangle for \(radius) "
   }
}

class Rectangle: Circle {
   var print = 7
   override var area: String {
      return super.area + " is now overridden as \(print)"
   }
}

let rect = Rectangle()
rect.radius = 25.0
rect.print = 3
print("Radius \(rect.area)")

class Square: Rectangle {
   override var radius: Double {
      didSet {
         print = Int(radius/5.0)+1
      }
   }
}

let sq = Square()
sq.radius = 100.0
print("Radius \(sq.area)")

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

<stdin>:14:18: error: var overrides a 'final' var
override var area: String {
^
<stdin>:7:9: note: overridden declaration is here
var area: String {
^
<stdin>:12:11: error: inheritance from a final class 'Circle'
class Rectangle: Circle {
^
<stdin>:25:14: error: var overrides a 'final' var
override var radius: Double {
^
<stdin>:6:14: note: overridden declaration is here
final var radius = 12.5

Da die Superklasse als 'final' deklariert ist und ihre Datentypen auch als 'final' deklariert sind, kann das Programm keine weiteren Unterklassen erstellen und es werden Fehler ausgegeben.

Klassen, Strukturen und Aufzählungen, die einmal in Swift 4 deklariert wurden, werden für die Vorbereitung der Instanz einer Klasse initialisiert. Der Anfangswert wird für gespeicherte Eigenschaften initialisiert, und auch für neue Instanzen werden die Werte initialisiert, um fortzufahren. Das Schlüsselwort zum Erstellen der Initialisierungsfunktion wird von der Methode 'init ()' ausgeführt. Der Swift 4-Initialisierer unterscheidet sich von Objective-C dadurch, dass er keine Werte zurückgibt. Seine Funktion besteht darin, vor der Verarbeitung zu überprüfen, ob neu erstellte Instanzen initialisiert wurden. Swift 4 bietet auch einen Deinitialisierungsprozess zum Ausführen von Speicherverwaltungsvorgängen, sobald die Zuordnung der Instanzen aufgehoben wurde.

Initialisierungsrolle für gespeicherte Eigenschaften

Gespeicherte Eigenschaften müssen die Instanzen für ihre Klassen und Strukturen initialisieren, bevor die Instanzen verarbeitet werden. Gespeicherte Eigenschaften verwenden den Initialisierer, um Werte zuzuweisen und zu initialisieren, wodurch das Aufrufen von Eigenschaftsbeobachtern entfällt. Der Initialisierer wird in gespeicherten Eigenschaften verwendet

  • So erstellen Sie einen Anfangswert.

  • So weisen Sie den Standardeigenschaftswert innerhalb der Eigenschaftsdefinition zu

  • Zum Initialisieren einer Instanz für einen bestimmten Datentyp wird 'init ()' verwendet. Innerhalb der Funktion init () werden keine Argumente übergeben.

Syntax

init() {
   //New Instance initialization goes here
}

Beispiel

struct rectangle {
   var length: Double
   var breadth: Double
   init() {
      length = 6
      breadth = 12
   }
}

var area = rectangle()
print("area of rectangle is \(area.length*area.breadth)")

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

area of rectangle is 72.0

Hier wird die Struktur 'Rechteck' mit der Länge und Breite der Elemente als 'Doppelte' Datentypen initialisiert. Die Methode Init () wird verwendet, um die Werte für die Länge und das Double der neu erstellten Elemente zu initialisieren. Die Fläche des Rechtecks ​​wird berechnet und durch Aufrufen der Rechteckfunktion zurückgegeben.

Standardmäßig Eigenschaftswerte festlegen

Die Sprache Swift 4 bietet die Funktion Init () zum Initialisieren der gespeicherten Eigenschaftswerte. Außerdem kann der Benutzer die Eigenschaftswerte standardmäßig initialisieren, während er die Klassen- oder Strukturelemente deklariert. Wenn die Eigenschaft im gesamten Programm denselben Wert annimmt, können wir ihn allein im Deklarationsabschnitt deklarieren, anstatt ihn in init () zu initialisieren. Durch das standardmäßige Festlegen von Eigenschaftswerten wird der Benutzer aktiviert, wenn die Vererbung für Klassen oder Strukturen definiert ist.

struct rectangle {
   var length = 6
   var breadth = 12
}

var area = rectangle()
print("area of rectangle is \(area.length*area.breadth)")

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

area of rectangle is 72

Anstatt in init () Länge und Breite zu deklarieren, werden hier die Werte in der Deklaration selbst initialisiert.

Parameter Initialisierung

In der Sprache Swift 4 kann der Benutzer Parameter als Teil der Definition des Initialisierers mit init () initialisieren.

struct Rectangle {
   var length: Double
   var breadth: Double
   var area: Double
   
   init(fromLength length: Double, fromBreadth breadth: Double) {
      self.length = length
      self.breadth = breadth
      area = length * breadth
   }
   init(fromLeng leng: Double, fromBread bread: Double) {
      self.length = leng
      self.breadth = bread
      area = leng * bread
   }
}

let ar = Rectangle(fromLength: 6, fromBreadth: 12)
print("area is: \(ar.area)")

let are = Rectangle(fromLeng: 36, fromBread: 12)
print("area is: \(are.area)")

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

area is: 72.0
area is: 432.0

Lokale und externe Parameter

Initialisierungsparameter haben sowohl lokale als auch globale Parameternamen, die denen von Funktions- und Methodenparametern ähnlich sind. Die lokale Parameterdeklaration wird verwendet, um auf den Initialisierungskörper zuzugreifen, und die externe Parameterdeklaration wird verwendet, um den Initialisierer aufzurufen. Swift 4-Initialisierer unterscheiden sich vom Funktions- und Methodeninitialisierer dadurch, dass sie nicht identifizieren, mit welchem ​​Initialisierer welche Funktionen aufgerufen werden.

Um dies zu überwinden, führt Swift 4 für jeden Parameter in init () einen automatischen externen Namen ein. Dieser automatische externe Name entspricht dem lokalen Namen, der vor jedem Initialisierungsparameter geschrieben wurde.

struct Days {
   let sunday, monday, tuesday: Int
   init(sunday: Int, monday: Int, tuesday: Int) {
      self.sunday = sunday
      self.monday = monday
      self.tuesday = tuesday
   }
   init(daysofaweek: Int) {
      sunday = daysofaweek
      monday = daysofaweek
      tuesday = daysofaweek
   }
}

let week = Days(sunday: 1, monday: 2, tuesday: 3)
print("Days of a Week is: \(week.sunday)")
print("Days of a Week is: \(week.monday)")
print("Days of a Week is: \(week.tuesday)")

let weekdays = Days(daysofaweek: 4)
print("Days of a Week is: \(weekdays.sunday)")
print("Days of a Week is: \(weekdays.monday)")
print("Days of a Week is: \(weekdays.tuesday)")

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

Days of a Week is: 1
Days of a Week is: 2
Days of a Week is: 3
Days of a Week is: 4
Days of a Week is: 4
Days of a Week is: 4

Parameter ohne externe Namen

Wenn für eine Initialisierung kein externer Name benötigt wird, wird der Unterstrich '_' verwendet, um das Standardverhalten zu überschreiben.

struct Rectangle {
   var length: Double
   
   init(frombreadth breadth: Double) {
      length = breadth * 10
   }
   init(frombre bre: Double) {
      length = bre * 30
   }
   init(_ area: Double) {
      length = area
   }
}

let rectarea = Rectangle(180.0)
print("area is: \(rectarea.length)")

let rearea = Rectangle(370.0)
print("area is: \(rearea.length)")

let recarea = Rectangle(110.0)
print("area is: \(recarea.length)")

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

area is: 180.0
area is: 370.0
area is: 110.0

Optionale Eigenschaftstypen

Wenn die gespeicherte Eigenschaft in einer Instanz keinen Wert zurückgibt, wird diese Eigenschaft mit einem 'optionalen' Typ deklariert, der angibt, dass für diesen bestimmten Typ 'kein Wert' zurückgegeben wird. Wenn die gespeicherte Eigenschaft als 'optional' deklariert wird, wird der Wert während der Initialisierung selbst automatisch auf 'nil' initialisiert.

struct Rectangle {
   var length: Double?
   
   init(frombreadth breadth: Double) {
      length = breadth * 10
   }
   init(frombre bre: Double) {
      length = bre * 30
   }
   init(_ area: Double) {
      length = area
   }
}

let rectarea = Rectangle(180.0)
print("area is: \(rectarea.length)")

let rearea = Rectangle(370.0)
print("area is: \(rearea.length)")

let recarea = Rectangle(110.0)
print("area is: \(recarea.length)")

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

area is: Optional(180.0)
area is: Optional(370.0)
area is: Optional(110.0)

Ändern der Konstanteneigenschaften während der Initialisierung

Durch die Initialisierung kann der Benutzer auch den Wert der konstanten Eigenschaft ändern. Während der Initialisierung ermöglicht die class-Eigenschaft, dass ihre Klasseninstanzen von der Superklasse und nicht von der Unterklasse geändert werden. Betrachten Sie zum Beispiel im vorherigen Programm, dass 'Länge' in der Hauptklasse als 'Variable' deklariert ist. Die folgende Programmvariable 'Länge' wird als 'Konstante' geändert.

struct Rectangle {
   let length: Double?
   
   init(frombreadth breadth: Double) {
      length = breadth * 10
   }
   init(frombre bre: Double) {
      length = bre * 30
   }
   init(_ area: Double) {
      length = area
   }
}

let rectarea = Rectangle(180.0)
print("area is: \(rectarea.length)")

let rearea = Rectangle(370.0)
print("area is: \(rearea.length)")

let recarea = Rectangle(110.0)
print("area is: \(recarea.length)")

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

area is: Optional(180.0)
area is: Optional(370.0)
area is: Optional(110.0)

Standardinitialisierer

Standardinitialisierer stellen eine neue Instanz für alle deklarierten Eigenschaften der Basisklasse oder -struktur mit Standardwerten bereit.

class defaultexample {
   var studname: String?
   var stmark = 98
   var pass = true
}
var result = defaultexample()

print("result is: \(result.studname)")
print("result is: \(result.stmark)")
print("result is: \(result.pass)")

Wenn wir über dem Programm auf dem Spielplatz laufen, erhalten wir folgendes Ergebnis. - -

result is: nil
result is: 98
result is: true

Das obige Programm wird mit dem Klassennamen 'defaultexample' definiert. Drei Mitgliedsfunktionen werden standardmäßig als 'Studname?' Initialisiert. Um 'Null'-Werte zu speichern,' stmark 'als 98 und' pass 'als Booleschen Wert' true '. Ebenso können die Elementwerte in der Klasse standardmäßig initialisiert werden, bevor die Klassenelementtypen verarbeitet werden.

Mitgliedsweise Initialisierer für Strukturtypen

Wenn die benutzerdefinierten Initialisierer nicht vom Benutzer bereitgestellt werden, erhalten Strukturtypen in Swift 4 automatisch den 'Mitgliedsinitialisierer'. Die Hauptfunktion besteht darin, die neuen Strukturinstanzen mit der Standardelementinitialisierung zu initialisieren. Anschließend werden die neuen Instanzeigenschaften nach Namen an die Mitgliedsinitialisierung übergeben.

struct Rectangle {
   var length = 100.0, breadth = 200.0
}
let area = Rectangle(length: 24.0, breadth: 32.0)

print("Area of rectangle is: \(area.length)")
print("Area of rectangle is: \(area.breadth)")

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

Area of rectangle is: 24.0
Area of rectangle is: 32.0

Strukturen werden standardmäßig für ihre Zugehörigkeitsfunktionen während der Initialisierung für 'Länge' als '100.0' und 'Breite' als '200.0' initialisiert. Die Werte werden jedoch während der Verarbeitung der Variablen Länge und Breite als 24.0 und 32.0 überschrieben.

Initialisierungsdelegation für Werttypen

Initializer-Delegierung ist definiert als Aufrufen von Initialisierern von anderen Initialisierern. Seine Hauptfunktion besteht darin, als Wiederverwendbarkeit zu fungieren, um Codeduplizierungen über mehrere Initialisierer hinweg zu vermeiden.

struct Stmark {
   var mark1 = 0.0, mark2 = 0.0
}
struct stdb {
   var m1 = 0.0, m2 = 0.0
}

struct block {
   var average = stdb()
   var result = Stmark()
   init() {}
   init(average: stdb, result: Stmark) {
      self.average = average
      self.result = result
   }

   init(avg: stdb, result: Stmark) {
      let tot = avg.m1 - (result.mark1 / 2)
      let tot1 = avg.m2 - (result.mark2 / 2)
      self.init(average: stdb(m1: tot, m2: tot1), result: result)
   }
}

let set1 = block()
print("student result is: \(set1.average.m1, set1.average.m2)
\(set1.result.mark1, set1.result.mark2)")

let set2 = block(average: stdb(m1: 2.0, m2: 2.0),
result: Stmark(mark1: 5.0, mark2: 5.0))
print("student result is: \(set2.average.m1, set2.average.m2)
\(set2.result.mark1, set2.result.mark2)")

let set3 = block(avg: stdb(m1: 4.0, m2: 4.0),
result: Stmark(mark1: 3.0, mark2: 3.0))
print("student result is: \(set3.average.m1, set3.average.m2)
\(set3.result.mark1, set3.result.mark2)")

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

(0.0,0.0) (0.0,0.0)
(2.0,2.0) 5.0,5.0)
(2.5,2.5) (3.0,3.0)

Regeln für die Initialisierungsdelegation

Werttypen Klassentypen
Die Vererbung wird für Werttypen wie Strukturen und Aufzählungen nicht unterstützt. Das Verweisen auf andere Initialisierer erfolgt über self.init Vererbung wird unterstützt. Überprüft, ob alle gespeicherten Eigenschaftswerte initialisiert wurden

Klassenvererbung und -initialisierung

Klassentypen haben zwei Arten von Initialisierern, um zu überprüfen, ob definierte gespeicherte Eigenschaften einen Anfangswert erhalten, nämlich bestimmte Initialisierer und Komfortinitialisierer.

Designated Initializers und Convenience Initializers

Designated Initializer Convenience Initializer
Wird als primäre Initialisierung für eine Klasse betrachtet Wird als unterstützende Initialisierung für eine Klasse angesehen
Alle Klasseneigenschaften werden initialisiert und der entsprechende Superklasseninitialisierer wird zur weiteren Initialisierung aufgerufen Der designierte Initialisierer wird mit dem praktischen Initialisierer aufgerufen, um eine Klasseninstanz für einen bestimmten Anwendungsfall oder Eingabewerttyp zu erstellen
Für jede Klasse ist mindestens ein bestimmter Initialisierer definiert Convenience-Initialisierer müssen nicht definiert werden, wenn für die Klasse keine Initialisierer erforderlich sind.
Init (Parameter) {Anweisungen} Convenience Init (Parameter) {Anweisungen}

Programm für Designated Initializers

class mainClass {
   var no1 : Int // local storage
   init(no1 : Int) {
      self.no1 = no1 // initialization
   }
}

class subClass : mainClass {
   var no2 : Int // new subclass storage
   init(no1 : Int, no2 : Int) {
      self.no2 = no2 // initialization
      super.init(no1:no1) // redirect to superclass
   }
}

let res = mainClass(no1: 10)
let print = subClass(no1: 10, no2: 20)

print("res is: \(res.no1)")
print("res is: \(print.no1)")
print("res is: \(print.no2)")

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

res is: 10
res is: 10
res is: 20

Programm für Convenience-Initialisierer

class mainClass {
   var no1 : Int // local storage
   init(no1 : Int) {
      self.no1 = no1 // initialization
   }
}

class subClass : mainClass {
   var no2 : Int
   init(no1 : Int, no2 : Int) {
      self.no2 = no2
      super.init(no1:no1)
   }
   // Requires only one parameter for convenient method
   override convenience init(no1: Int) {
      self.init(no1:no1, no2:0)
   }
}

let res = mainClass(no1: 20)
let print = subClass(no1: 30, no2: 50)

print("res is: \(res.no1)")
print("res is: \(print.no1)")
print("res is: \(print.no2)")

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

res is: 20
res is: 30
res is: 50

Vererbung und Überschreiben des Initialisierers

Swift 4 erlaubt seinen Unterklassen standardmäßig nicht, seine Superklassen-Initialisierer für ihre Elementtypen zu erben. Die Vererbung gilt nur in einem gewissen Umfang für Super-Class-Initialisierer, der unter Vererbung von automatischen Initialisierern erläutert wird.

Wenn für den Benutzer Initialisierer in der Superklasse definiert sein müssen, muss der Benutzer eine Unterklasse mit Initialisierern als benutzerdefinierte Implementierung definieren. Wenn das Überschreiben durch die Unterklasse erfolgen soll, muss das Schlüsselwort 'override' der Superklasse deklariert werden.

class sides {
   var corners = 4
   var description: String {
      return "\(corners) sides"
   }
}

let rectangle = sides()
print("Rectangle: \(rectangle.description)")

class pentagon: sides {
   override init() {
      super.init()
      corners = 5
   }
}

let bicycle = pentagon()
print("Pentagon: \(bicycle.description)")

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

Rectangle: 4 sides
Pentagon: 5 sides

Designated und Convenience Initializer in Aktion

class Planet {
   var name: String
   init(name: String) {
      self.name = name
   }
   convenience init() {
      self.init(name: "[No Planets]")
   }
}

let plName = Planet(name: "Mercury")
print("Planet name is: \(plName.name)")

let noplName = Planet()
print("No Planets like that: \(noplName.name)")

class planets: Planet {
   var count: Int
   init(name: String, count: Int) {
      self.count = count
      super.init(name: name)
   }
   override convenience init(name: String) {
      self.init(name: name, count: 1)
   }
}

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

Planet name is: Mercury
No Planets like that: [No Planets]

Failable Initializer

Der Benutzer muss benachrichtigt werden, wenn beim Definieren einer Klasse, Struktur oder Aufzählungswerte Initialisierungsfehler auftreten. Die Initialisierung von Variablen wird manchmal aufgrund von - zu einem Fehler

  • Ungültige Parameterwerte.
  • Fehlen der erforderlichen externen Quelle.
  • Bedingung, die verhindert, dass die Initialisierung erfolgreich ist.

Um Ausnahmen zu erfassen, die durch die Initialisierungsmethode ausgelöst werden, erstellt Swift 4 eine flexible Initialisierung mit dem Namen "Failable Initialisierer", um den Benutzer darüber zu informieren, dass beim Initialisieren der Struktur-, Klassen- oder Aufzählungselemente etwas unbemerkt bleibt. Das Schlüsselwort zum Abfangen des fehlgeschlagenen Initialisierers lautet "init?". Außerdem können fehlgeschlagene und nicht ausfallbare Initialisierer nicht mit denselben Parametertypen und -namen definiert werden.

struct studrecord {
   let stname: String
   init?(stname: String) {
      if stname.isEmpty {return nil }
      self.stname = stname
   }
}
let stmark = studrecord(stname: "Swing")

if let name = stmark {
   print("Student name is specified")
}
let blankname = studrecord(stname: "")

if blankname == nil {
   print("Student name is left blank")
}

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

Student name is specified
Student name is left blank

Verfügbare Initialisierer für Aufzählungen

Die Sprache Swift 4 bietet die Flexibilität, Failable-Initialisierer auch für Aufzählungen zu haben, um den Benutzer zu benachrichtigen, wenn die Aufzählungsmitglieder keine Werte mehr initialisieren können.

enum functions {
   case a, b, c, d
   init?(funct: String) {
      switch funct {
      case "one":
         self = .a
      case "two":
         self = .b
      case "three":
         self = .c
      case "four":
         self = .d
      default:
         return nil
      }
   }
}
let result = functions(funct: "two")

if result != nil {
   print("With In Block Two")
}
let badresult = functions(funct: "five")

if badresult == nil {
   print("Block Does Not Exist")
}

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

With In Block Two
Block Does Not Exist

Verfügbare Initialisierer für Klassen

Ein fehlgeschlagener Initialisierer, der mit Aufzählungen und Strukturen deklariert wird, warnt unter allen Umständen innerhalb seiner Implementierung einen Initialisierungsfehler. Ein fehlgeschlagener Initialisierer in Klassen warnt den Fehler jedoch erst, nachdem die gespeicherten Eigenschaften auf einen Anfangswert festgelegt wurden.

class studrecord {
   let studname: String!
   init?(studname: String) {
      self.studname = studname
      if studname.isEmpty { return nil }
   }
}

if let stname = studrecord(studname: "Failable Initializers") {
   print("Module is \(stname.studname)")
}

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

Module is Optional("Failable Initializers")

Überschreiben eines fehlgeschlagenen Initialisierers

Wie beim Initialisieren hat der Benutzer auch die Möglichkeit, einen fehlgeschlagenen Initialisierer der Oberklasse innerhalb der Unterklasse zu überschreiben. Die fehlgeschlagene Initialisierung der Superklasse kann auch in einem nicht fehlgeschlagenen Initialisierer der Unterklasse überschrieben werden.

Der Unterklasseninitialisierer kann nicht an den Superklasseninitialisierer delegieren, wenn ein fehlgeschlagener Superklasseninitialisierer mit einer nicht ausfallbaren Unterklasseninitialisierung überschrieben wird.

Ein nicht ausfallbarer Initialisierer kann niemals an einen ausfallbaren Initialisierer delegieren.

Das unten angegebene Programm beschreibt die fehlgeschlagenen und nicht ausfallbaren Initialisierer.

class Planet {
   var name: String
   
   init(name: String) {
      self.name = name
   }
   convenience init() {
      self.init(name: "[No Planets]")
   }
}
let plName = Planet(name: "Mercury")
print("Planet name is: \(plName.name)")

let noplName = Planet()
print("No Planets like that: \(noplName.name)")
   
class planets: Planet {
   var count: Int
   
   init(name: String, count: Int) {
      self.count = count
      super.init(name: name)
   }
   override convenience init(name: String) {
      self.init(name: name, count: 1)
   }
}

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

Planet name is: Mercury
No Planets like that: [No Planets]

Der Init! Failable Initializer

Swift 4 bietet 'init?' um einen optionalen fehlgeschlagenen Instanzinitialisierer zu definieren. Definieren einer implizit entpackten optionalen Instanz des spezifischen Typs 'init!' angegeben.

struct studrecord {
let stname: String

   init!(stname: String) {
      if stname.isEmpty {return nil }
      self.stname = stname
   }
}
let stmark = studrecord(stname: "Swing")

if let name = stmark {
   print("Student name is specified")
}

let blankname = studrecord(stname: "")

if blankname == nil {
   print("Student name is left blank")
}

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

Student name is specified
Student name is left blank

Erforderliche Initialisierer

Um jede Unterklasse des Schlüsselworts 'Initialisieren' erforderlich zu deklarieren, muss vor der Funktion init () definiert werden.

class classA {
   required init() {
      var a = 10
      print(a)
   }
}

class classB: classA {
   required init() {
      var b = 30
      print(b)
   }
}

let res = classA()
let print = classB()

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

10
30
10

Bevor eine Klasseninstanz freigegeben werden muss, muss 'deinitializer' aufgerufen werden, um die Zuweisung des Speicherplatzes aufzuheben. Das Schlüsselwort 'deinit' wird verwendet, um die von den Systemressourcen belegten Speicherplätze freizugeben. Die Deinitialisierung ist nur für Klassentypen verfügbar.

Deinitialisierung zur Freigabe des Speicherplatzes

Swift 4 gibt Ihre Instanzen automatisch frei, wenn sie nicht mehr benötigt werden, um Ressourcen freizugeben. Swift 4 übernimmt die Speicherverwaltung von Instanzen durch automatische Referenzzählung (ARC), wie unter Automatische Referenzzählung beschrieben. Normalerweise müssen Sie keine manuelle Bereinigung durchführen, wenn Ihre Instanzen freigegeben werden. Wenn Sie jedoch mit Ihren eigenen Ressourcen arbeiten, müssen Sie möglicherweise selbst zusätzliche Bereinigungen durchführen. Wenn Sie beispielsweise eine benutzerdefinierte Klasse erstellen, um eine Datei zu öffnen und Daten in diese zu schreiben, müssen Sie die Datei möglicherweise schließen, bevor die Zuordnung der Klasseninstanz aufgehoben wird.

var counter = 0; // for reference counting
class baseclass {
   init() {
      counter++;
   }
   deinit {
      counter--;
   }
}
var print: baseclass? = baseclass()

print(counter)
print = nil
print(counter)

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

1
0

Wenn die Anweisung print = nil weggelassen wird, bleiben die Werte des Zählers gleich, da er nicht deinitialisiert ist.

var counter = 0; // for reference counting

class baseclass {
   init() {
      counter++;
   }
   deinit {
      counter--;
   }
}
var print: baseclass? = baseclass()
print(counter)
print(counter)

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

1
1

Speicherverwaltungsfunktionen und deren Verwendung werden in der Sprache Swift 4 durch automatische Referenzzählung (ARC) behandelt. ARC wird zum Initialisieren und Deinitialisieren der Systemressourcen verwendet, wodurch Speicherplätze freigegeben werden, die von den Klasseninstanzen verwendet werden, wenn die Instanzen nicht mehr benötigt werden. ARC verfolgt Informationen über die Beziehungen zwischen unseren Code-Instanzen, um die Speicherressourcen effektiv zu verwalten.

Funktionen von ARC

  • ARC weist einen Speicherblock zu, um die Informationen jedes Mal zu speichern, wenn eine neue Klasseninstanz von init () erstellt wird.

  • Informationen über den Instanztyp und seine Werte werden gespeichert.

  • Wenn die Klasseninstanz nicht mehr benötigt wird, gibt sie automatisch den Speicherplatz durch deinit () für das weitere Speichern und Abrufen von Klasseninstanzen frei.

  • ARC verfolgt die aktuell verweisenden Eigenschaften, Konstanten und Variablen von Klasseninstanzen, sodass deinit () nur auf diese nicht verwendeten Instanzen angewendet wird.

  • ARC behält einen 'starken Verweis' auf diese Klasseninstanzeigenschaften, Konstanten und Variablen bei, um die Freigabe zu beschränken, wenn die Klasseninstanz derzeit verwendet wird.

ARC-Programm

class StudDetails {
   var stname: String!
   var mark: Int!
   
   init(stname: String, mark: Int) {
      self.stname = stname
      self.mark = mark
   }
   deinit {
      print("Deinitialized \(self.stname)")
      print("Deinitialized \(self.mark)")
   }
}

let stname = "Swift 4"
let mark = 98

print(stname)
print(mark)

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

Swift 4
98

Klasseninstanzen für starke ARC-Referenzzyklen

class studmarks {
   let name: String
   var stud: student?
   
   init (name: String) {
      print("Initializing: \(name)")
      self.name = name
   }
   deinit {
      print("Deallocating: \(self.name)")
   }
}

class student {
   let name: String
   var strname: studmarks?
   
   init (name: String) {
      print("Initializing: \(name)")
      self.name = name
   }
   deinit {
      print("Deallocating: \(self.name)")
   }
}

var shiba: studmarks?
var mari: student?

shiba = studmarks(name: "Swift 4")
mari = student(name: "ARC")

shiba!.stud = mari
mari!.strname = shiba

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

Initializing: Swift 4
Initializing: ARC

ARC Schwache und nicht besessene Referenzen

Klassentyp-Eigenschaften bieten zwei Möglichkeiten, um starke Referenzzyklen aufzulösen:

  • Schwache Referenzen
  • Nicht besessene Referenzen

Diese Referenzen werden verwendet, um es einer Instanz zu ermöglichen, andere Instanzen in einem Referenzzyklus zu referenzieren. Dann können sich die Instanzen auf jede einzelne Instanz beziehen, anstatt sich um einen starken Referenzzyklus zu kümmern. Wenn der Benutzer weiß, dass eine Instanz möglicherweise 'Null'-Werte zurückgibt, können wir darauf hinweisen, dass eine schwache Referenz verwendet wird. Wenn die Instanz etwas zurückgibt und nicht Null, deklarieren Sie es mit einem nicht besessenen Verweis.

Schwaches Referenzprogramm

class module {
   let name: String
   init(name: String) { self.name = name }
   var sub: submodule?
   deinit { print("\(name) Is The Main Module") }
}

class submodule {
   let number: Int
   init(number: Int) { self.number = number }
   weak var topic: module?

   deinit { print("Sub Module with its topic number is \(number)") }
}

var toc: module?
var list: submodule?
toc = module(name: "ARC")
list = submodule(number: 4)
toc!.sub = list
list!.topic = toc

toc = nil
list = nil

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

ARC Is The Main Module
Sub Module with its topic number is 4

Nicht besessenes Referenzprogramm

class student {
   let name: String
   var section: marks?
   init(name: String) {
      self.name = name
   }
   deinit { print("\(name)") }
}

class marks {
   let marks: Int
   unowned let stname: student
   
   init(marks: Int, stname: student) {
      self.marks = marks
      self.stname = stname
   }
   deinit { print("Marks Obtained by the student is \(marks)") }
}

var module: student?
module = student(name: "ARC")
module!.section = marks(marks: 98, stname: module!)
module = nil

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

ARC
Marks Obtained by the student is 98

Starke Referenzzyklen für Verschlüsse

Wenn wir der Klasseninstanzeigenschaft und dem Hauptteil der Schließung einen Abschluss zuweisen, um eine bestimmte Instanz zu erfassen, kann ein starker Referenzzyklus auftreten. Ein starker Verweis auf den Abschluss wird durch 'self.someProperty' oder 'self.someMethod ()' definiert. Starke Referenzzyklen werden als Referenztypen für die Verschlüsse verwendet.

class HTMLElement {
   let samplename: String
   let text: String?
   
   lazy var asHTML: () -> String = {
      if let text = self.text {
         return "<\(self.samplename)>\(text)</\(self.samplename)>"
      } else {
         return "<\(self.samplename) />"
      }
   }
   init(samplename: String, text: String? = nil) {
      self.samplename = samplename
      self.text = text
   }
   deinit {
      print("\(samplename) is being deinitialized")
   }
}

var paragraph: HTMLElement? = HTMLElement(samplename: "p", text: "Welcome to Closure SRC")
print(paragraph!.asHTML())

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

<p>Welcome to Closure SRC</p>

Schwache und nicht besessene Referenzen

Wenn der Abschluss und die Instanz aufeinander verweisen, kann der Benutzer die Erfassung in einem Abschluss als nicht besessene Referenz definieren. Dann würde es dem Benutzer nicht erlauben, die Instanz gleichzeitig freizugeben. Wenn die Instanz irgendwann einen 'Null'-Wert zurückgibt, definieren Sie den Abschluss mit der schwachen Instanz.

class HTMLElement {
   let module: String
   let text: String?
   
   lazy var asHTML: () -> String = {
      [unowned self] in
      if let text = self.text {
         return "<\(self.module)>\(text)</\(self.module)>"
      } else {
         return "<\(self.module) />"
      }
   }
   init(module: String, text: String? = nil) {
      self.module = module
      self.text = text
   }
   deinit {
      print("\(module) the deinit()")
   }
}

var paragraph: HTMLElement? = HTMLElement(module: "Inside", text: "ARC Weak References")
print(paragraph!.asHTML())
paragraph = nil

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

<Inside>ARC Weak References</Inside>
Inside the deinit()

Das Abfragen, Aufrufen von Eigenschaften, Indizes und Methoden für ein optionales Element, das möglicherweise 'nil' ist, wird als optionale Verkettung definiert. Optionale Verkettung gibt zwei Werte zurück -

  • Wenn das optionale Element einen 'Wert' enthält, werden beim Aufrufen der zugehörigen Eigenschaft, Methoden und Indizes Werte zurückgegeben

  • Wenn das optionale Element den Wert 'nil' enthält, geben alle zugehörigen Eigenschaften, Methoden und Indizes nil zurück

Da mehrere Abfragen zu Methoden, Eigenschaften und Indizes zu einer Kette zusammengefasst werden, wirkt sich ein Fehler in einer Kette auf die gesamte Kette aus und führt zu einem Nullwert.

Optionale Verkettung als Alternative zum erzwungenen Auspacken

Die optionale Verkettung wird nach dem optionalen Wert mit '?' um eine Eigenschaft, Methode oder einen Index aufzurufen, wenn der optionale Wert einige Werte zurückgibt.

Optionale Verkettung '?' Zugriff auf Methoden, Eigenschaften und IndizesOptional Chaining '!' Auspacken erzwingen
? wird nach dem optionalen Wert zum Aufrufen von Eigenschaft, Methode oder Index platziert ! wird nach dem optionalen Wert platziert, um die Eigenschaft, Methode oder den Index aufzurufen und das Entpacken des Werts zu erzwingen
Schlägt ordnungsgemäß fehl, wenn das optionale Element "Null" ist. Das erzwungene Auspacken löst einen Laufzeitfehler aus, wenn das optionale Element 'nil' ist.

Programm zur optionalen Verkettung mit '!'

class ElectionPoll {
   var candidate: Pollbooth?
}

lass Pollbooth {
   var name = "MP"
}

let cand = ElectionPoll()
let candname = cand.candidate!.name

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

fatal error: unexpectedly found nil while unwrapping an Optional value
0 Swift 4 0x0000000103410b68
llvm::sys::PrintStackTrace(__sFILE*) + 40
1 Swift 4 0x0000000103411054 SignalHandler(int) + 452
2 libsystem_platform.dylib 0x00007fff9176af1a _sigtramp + 26
3 libsystem_platform.dylib 0x000000000000000b _sigtramp + 1854492939
4 libsystem_platform.dylib 0x00000001074a0214 _sigtramp + 1976783636
5 Swift 4 0x0000000102a85c39
llvm::JIT::runFunction(llvm::Function*, std::__1::vector > const&) + 329
6 Swift 4 0x0000000102d320b3
llvm::ExecutionEngine::runFunctionAsMain(llvm::Function*,
std::__1::vector<std::__1::basic_string, std::__1::allocator >,
std::__1::allocator<std::__1::basic_string, std::__1::allocator > > > const&,
char const* const*) + 1523
7 Swift 4 0x000000010296e6ba Swift 4::RunImmediately(Swift
4::CompilerInstance&, std::__1::vector<std::__1::basic_string,
std::__1::allocator >, std::__1::allocator<std::__1::basic_string,
std::__1::allocator > > > const&, Swift 4::IRGenOptions&, Swift 4::SILOptions
const&) + 1066
8 Swift 4 0x000000010275764b frontend_main(llvm::ArrayRef,
char const*, void*) + 5275
9 Swift 4 0x0000000102754a6d main + 1677
10 libdyld.dylib 0x00007fff8bb9e5c9 start + 1
11 libdyld.dylib 0x000000000000000c start + 1950751300
Stack dump:
0. Program arguments:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/
usr/bin/Swift 4 -frontend -interpret - -target x86_64-apple-darwin14.0.0 -
target-cpu core2 -sdk
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/
SDKs/MacOSX10.10.sdk -module-name main
/bin/sh: line 47: 15672 Done cat <<'SWIFT 4'
import Foundation
</std::__1::basic_string</std::__1::basic_string</std::__1::basic_string</std::
__1::basic_string

Das obige Programm deklariert "Wahlumfrage" als Klassennamen und enthält "Kandidat" als Mitgliedschaftsfunktion. Die Unterklasse wird als 'Wahlkabine' und 'Name' als Zugehörigkeitsfunktion deklariert, die als 'MP' initialisiert wird. Der Aufruf der Superklasse wird durch Erstellen einer Instanz 'cand' mit optionalem '!' Initialisiert. Da die Werte nicht in ihrer Basisklasse deklariert sind, wird der Wert 'nil' gespeichert, wodurch ein schwerwiegender Fehler durch das Erzwingen des Entpackens zurückgegeben wird.

Programm für optionale Verkettung mit '?'

class ElectionPoll {
   var candidate: Pollbooth?
}

class Pollbooth {
   var name = "MP"
}
let cand = ElectionPoll()

if let candname = cand.candidate?.name {
   print("Candidate name is \(candname)")
} else {
   print("Candidate name cannot be retreived")
}

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

Candidate name cannot be retreived

Das obige Programm deklariert "Wahlumfrage" als Klassennamen und enthält "Kandidat" als Mitgliedschaftsfunktion. Die Unterklasse wird als 'Wahlkabine' und 'Name' als Zugehörigkeitsfunktion deklariert, die als 'MP' initialisiert wird. Der Aufruf der Superklasse wird durch Erstellen einer Instanz 'cand' mit optionalem '?' Initialisiert. Da die Werte nicht in ihrer Basisklasse deklariert sind, wird der Wert 'nil' vom else-Handlerblock in der Konsole gespeichert und gedruckt.

Definieren von Modellklassen für optionale Verkettung und Zugriff auf Eigenschaften

Die Sprache Swift 4 bietet auch das Konzept der optionalen Verkettung, um mehr als eine Unterklasse als Modellklassen zu deklarieren. Dieses Konzept ist sehr nützlich, um komplexe Modelle zu definieren und auf die Eigenschaften von Eigenschaften, Methoden und Indizes zuzugreifen.

class rectangle {
   var print: circle?
}

class circle {
   var area = [radius]()
   var cprint: Int {
      return area.count
   }
   subscript(i: Int) -> radius {
      get {
         return area[i]
      }
      set {
         area[i] = newValue
      }
   }
   func circleprint() {
      print("The number of rooms is \(cprint)")
   }
   var rectarea: circumference?
}

class radius {
   let radiusname: String
   init(radiusname: String) { self.radiusname = radiusname }
}

class circumference {
   var circumName: String?
   var circumNumber: String?
   var street: String?

   func buildingIdentifier() -> String? {
      if circumName != nil {
         return circumName
      } else if circumNumber != nil {
         return circumNumber
      } else {
         return nil
      }
   }
}

let rectname = rectangle()
if let rectarea = rectname.print?.cprint {
   print("Area of rectangle is \(rectarea)")
} else {
   print("Rectangle Area is not specified")
}

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

Rectangle Area is not specified

Aufrufmethoden durch optionale Verkettung

class rectangle {
   var print: circle?
}

class circle {
   var area = [radius]()
   var cprint: Int {
      return area.count
   }
   subscript(i: Int) -> radius {
      get {
         return area[i]
      }
      set {
         area[i] = newValue
      }
   }

   func circleprint() {
      print("Area of Circle is: \(cprint)")
   }
   var rectarea: circumference?
}

class radius {
   let radiusname: String
   init(radiusname: String) { self.radiusname = radiusname }
}

class circumference {
   var circumName: String?
   var circumNumber: String?
   var circumarea: String?
   
   func buildingIdentifier() -> String? {
      if circumName != nil {
         return circumName
      } else if circumNumber != nil {
         return circumNumber
      } else {
         return nil
      }
   }
}

let circname = rectangle()

if circname.print?.circleprint() != nil {
   print("Area of circle is specified)")
} else {
   print("Area of circle is not specified")
}

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

Area of circle is not specified

Die in der Unterklasse circle () deklarierte Funktion circleprint () wird durch Erstellen einer Instanz mit dem Namen 'circname' aufgerufen. Die Funktion gibt einen Wert zurück, wenn sie einen Wert enthält, andernfalls gibt sie eine benutzerdefinierte Drucknachricht zurück, indem sie die Anweisung 'if circname.print? .Circleprint ()! = Nil' überprüft.

Zugriff auf Indizes über optionale Verkettung

Die optionale Verkettung wird verwendet, um einen Indexwert festzulegen und abzurufen, um zu überprüfen, ob der Aufruf dieses Index einen Wert zurückgibt. '?' wird vor die tiefgestellten Klammern gesetzt, um auf den optionalen Wert des jeweiligen Index zuzugreifen.

Programm 1

class rectangle {
   var print: circle?
}

class circle {
   var area = [radius]()
   var cprint: Int {
      return area.count
   }
   subscript(i: Int) -> radius {
      get {
         return area[i]
      }
      set {
         area[i] = newValue
      }
   }
   func circleprint() {
      print("The number of rooms is \(cprint)")
   }
   var rectarea: circumference?
}

class radius {
   let radiusname: String
   init(radiusname: String) { self.radiusname =  radiusname }
}

class circumference {
   var circumName: String?
   var circumNumber: String?
   var circumarea: String?
   
   func buildingIdentifier() -> String? {
      if circumName != nil {
         return circumName
      } else if circumNumber != nil {
         return circumNumber
      } else {
         return nil
      }
   }
}

let circname = rectangle()

if let radiusName = circname.print?[0].radiusname {
   print("The first room name is \(radiusName).")
} else {
   print("Radius is not specified.")
}

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

Radius is not specified.

Im obigen Programm sind die Instanzwerte für die Zugehörigkeitsfunktion 'radiusName' nicht angegeben. Daher gibt der Programmaufruf der Funktion nur einen anderen Teil zurück, während wir die Werte für die jeweilige Zugehörigkeitsfunktion definieren müssen, um die Werte zurückzugeben.

Programm 2

class rectangle {
   var print: circle?
}

class circle {
   var area = [radius]()
   var cprint: Int {
      return area.count
   }
   subscript(i: Int) -> radius {
      get {
         return area[i]
      }
      set {
         area[i] = newValue
      }
   }
   func circleprint() {
      print("The number of rooms is \(cprint)")
   }
   var rectarea: circumference?
}

class radius {
   let radiusname: String
   init(radiusname: String) { self.radiusname = radiusname }
}

class circumference {
   var circumName: String?
   var circumNumber: String?
   var circumarea: String?
   
   func buildingIdentifier() -> String? {
      if circumName != nil {
         return circumName
      } else if circumNumber != nil {
         return circumNumber
      } else {
         return nil
      }
   }
}

let circname = rectangle()
circname.print?[0] = radius(radiusname: "Diameter")
let printing = circle()

printing.area.append(radius(radiusname: "Units"))
printing.area.append(radius(radiusname: "Meter"))
circname.print = printing

if let radiusName = circname.print?[0].radiusname {
   print("Radius is measured in \(radiusName).")
} else {
   print("Radius is not specified.")
}

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

Radius is measured in Units.

Im obigen Programm werden die Instanzwerte für die Zugehörigkeitsfunktion 'radiusName' angegeben. Daher gibt der Programmaufruf der Funktion jetzt Werte zurück.

Zugriff auf Indizes vom optionalen Typ

class rectangle {
   var print: circle?
}

class circle {
   var area = [radius]()
   var cprint: Int {
      return area.count
   }

   subscript(i: Int) -> radius {
      get {
         return area[i]
      }
      set {
         area[i] = newValue
      }
   }
   func circleprint() {
      print("The number of rooms is \(cprint)")
   }
   var rectarea: circumference?
}

class radius {
   let radiusname: String
   init(radiusname: String) { self.radiusname = radiusname }
}

class circumference {
   var circumName: String?
   var circumNumber: String?
   var circumarea: String?
   
   func buildingIdentifier() -> String? {
      if circumName != nil {
         return circumName
      } else if circumNumber != nil {
         return circumNumber
      } else {
         return nil
      }
   }
}

let circname = rectangle()
circname.print?[0] = radius(radiusname: "Diameter")

let printing = circle()
printing.area.append(radius(radiusname: "Units"))
printing.area.append(radius(radiusname: "Meter"))
circname.print = printing

var area = ["Radius": [35, 45, 78, 101], "Circle": [90, 45, 56]]
area["Radius"]?[1] = 78
area["Circle"]?[1]--

print(area["Radius"]?[0])
print(area["Radius"]?[1])
print(area["Radius"]?[2])
print(area["Radius"]?[3])

print(area["Circle"]?[0])
print(area["Circle"]?[1])
print(area["Circle"]?[2])

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

Optional(35)
Optional(78)
Optional(78)
Optional(101)
Optional(90)
Optional(44)
Optional(56)

Auf die optionalen Werte für Indizes kann zugegriffen werden, indem auf deren Indexwerte verwiesen wird. Es kann als Index [0], Index [1] usw. zugegriffen werden. Die Standard-Indexwerte für 'Radius' werden zuerst als [35, 45, 78, 101] und für 'Kreis' [90, 45, 56] zugewiesen.] . Dann werden die tiefgestellten Werte als Radius [0] auf 78 und Kreis [1] auf 45 geändert.

Verknüpfung mehrerer Verkettungsebenen

Durch optionale Verkettung können auch mehrere Unterklassen mit den Methoden, Eigenschaften und Indizes der Superklassen verknüpft werden.

Mehrfachverkettung von optional kann verknüpft werden -

Wenn das Abrufen des Typs nicht optional ist, gibt die optionale Verkettung einen optionalen Wert zurück. Wenn beispielsweise String durch optionale Verkettung String zurückgibt? Wert

class rectangle {
   var print: circle?
}

class circle {
   var area = [radius]()
   var cprint: Int {
      return area.count
   }
   subscript(i: Int) -> radius {
      get {
         return area[i]
      }
      set {
         area[i] = newValue
      }
   }
   func circleprint() {
      print("The number of rooms is \(cprint)")
   }
   var rectarea: circumference?
}

class radius {
   let radiusname: String
   init(radiusname: String) { self.radiusname = radiusname }
}

class circumference {
   var circumName: String?
   var circumNumber: String?
   var circumarea: String?

   func buildingIdentifier() -> String? {
      if circumName != nil {
         return circumName
      } else if circumNumber != nil {
         return circumNumber
      } else {
         return nil
      }
   }
}

let circname = rectangle()

if let radiusName = circname.print?[0].radiusname {
   print("The first room name is \(radiusName).")
} else {
   print("Radius is not specified.")
}

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

Radius is not specified.

Im obigen Programm sind die Instanzwerte für die Zugehörigkeitsfunktion 'radiusName' nicht angegeben. Daher gibt der Programmaufruf der Funktion nur einen anderen Teil zurück, während wir zum Zurückgeben der Werte die Werte für die bestimmte Zugehörigkeitsfunktion definieren müssen.

Wenn der Abruftyp bereits optional ist, gibt die optionale Verkettung auch einen optionalen Wert zurück. Zum Beispiel wenn String? Wird über eine optionale Verkettung zugegriffen, wird ein String zurückgegeben? Wert..

class rectangle {
   var print: circle?
}

class circle {
   var area = [radius]()
   var cprint: Int {
      return area.count
   }
   subscript(i: Int) -> radius {
      get {
         return area[i]
      }
      set {
         area[i] = newValue
      }
   }
   func circleprint() {
      print("The number of rooms is \(cprint)")
   }
   var rectarea: circumference?
}

class radius {
   let radiusname: String
   init(radiusname: String) { self.radiusname = radiusname }
}

class circumference {
   var circumName: String?
   var circumNumber: String?
   var circumarea: String?
   
   func buildingIdentifier() -> String? {
      if circumName != nil {
         return circumName
      } else if circumNumber != nil {
         return circumNumber
      } else {
         return nil
      }
   }
}

let circname = rectangle()
circname.print?[0] = radius(radiusname: "Diameter")
let printing = circle()

printing.area.append(radius(radiusname: "Units"))
printing.area.append(radius(radiusname: "Meter"))
circname.print = printing

if let radiusName = circname.print?[0].radiusname {
   print("Radius is measured in \(radiusName).")
} else {
   print("Radius is not specified.")
}

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

Radius is measured in Units.

Im obigen Programm werden die Instanzwerte für die Zugehörigkeitsfunktion 'radiusName' angegeben. Daher gibt der Programmaufruf der Funktion jetzt Werte zurück.

Verkettung von Methoden mit optionalen Rückgabewerten

Die optionale Verkettung wird auch verwendet, um auf unterklassendefinierte Methoden zuzugreifen.

class rectangle {
   var print: circle?
}

class circle {
   var area = [radius]()
   var cprint: Int {
      return area.count
   }
   subscript(i: Int) -> radius {
      get {
         return area[i]
      }
      set {
         area[i] = newValue
      }
   }
   func circleprint() {
      print("Area of Circle is: \(cprint)")
   }
   var rectarea: circumference?
}

class radius {
   let radiusname: String
   init(radiusname: String) { self.radiusname = radiusname }
}

class circumference {
   var circumName: String?
   var circumNumber: String?
   var circumarea: String?
   
   func buildingIdentifier() -> String? {
      if circumName != nil {
         return circumName
      } else if circumNumber != nil {
         return circumNumber
      } else {
         return nil
      }
   }
}

let circname = rectangle()

if circname.print?.circleprint() != nil {
   print("Area of circle is specified)")
} else {
   print("Area of circle is not specified")
}

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

Area of circle is not specified

Um den Typ einer Instanz zu überprüfen, kommt 'Type Casting' in der Sprache Swift 4 ins Spiel. Es wird verwendet, um zu überprüfen, ob der Instanztyp zu einer bestimmten Superklasse oder Unterklasse gehört oder in einer eigenen Hierarchie definiert ist.

Swift 4 Type Casting bietet zwei Operatoren 'is', um den Typ eines Werts und 'as' zu überprüfen und den Typwert in einen anderen Typ umzuwandeln. Das Typumwandeln prüft auch, ob der Instanztyp einem bestimmten Protokollkonformitätsstandard entspricht.

Definieren einer Klassenhierarchie

Mit Type Casting wird der Instanztyp überprüft, um festzustellen, ob er zu einem bestimmten Klassentyp gehört. Außerdem wird die Hierarchie der Klassen und ihrer Unterklassen überprüft, um diese Instanzen zu überprüfen und umzuwandeln, damit sie zu derselben Hierarchie werden.

class Subjects {
   var physics: String
   init(physics: String) {
      self.physics = physics
   }
}

class Chemistry: Subjects {
   var equations: String
   init(physics: String, equations: String) {
      self.equations = equations
      super.init(physics: physics)
   }
}

class Maths: Subjects {
   var formulae: String
   init(physics: String, formulae: String) {
      self.formulae = formulae
      super.init(physics: physics)
   }
}

let sa = [ Chemistry(physics: "solid physics", equations: "Hertz"),
   Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz")]

let samplechem = Chemistry(physics: "solid physics", equations: "Hertz")
print("Instance physics is: \(samplechem.physics)")
print("Instance equation is: \(samplechem.equations)")

let samplemaths = Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz")
print("Instance physics is: \(samplemaths.physics)")
print("Instance formulae is: \(samplemaths.formulae)")

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

Instance physics is: solid physics
Instance equation is: Hertz
Instance physics is: Fluid Dynamics
Instance formulae is: Giga Hertz

Typprüfung

Die Typprüfung erfolgt mit dem Operator 'is'. Der Typprüfungsoperator 'is' prüft, ob die Instanz zu einem bestimmten Unterklassentyp gehört, und gibt 'true' zurück, wenn sie zu dieser Instanz gehört, andernfalls wird 'false' zurückgegeben.

class Subjects {
   var physics: String
   init(physics: String) {
      self.physics = physics
   }
}

class Chemistry: Subjects {
   var equations: String
   init(physics: String, equations: String) {
      self.equations = equations
      super.init(physics: physics)
   }
}

class Maths: Subjects {
   var formulae: String
   init(physics: String, formulae: String) {
      self.formulae = formulae
      super.init(physics: physics)
   }
}

let sa = [
   Chemistry(physics: "solid physics", equations: "Hertz"),
   Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz"),
   Chemistry(physics: "Thermo physics", equations: "Decibels"),
   Maths(physics: "Astro Physics", formulae: "MegaHertz"),
   Maths(physics: "Differential Equations", formulae: "Cosine Series")]

let samplechem = Chemistry(physics: "solid physics", equations: "Hertz")
print("Instance physics is: \(samplechem.physics)")
print("Instance equation is: \(samplechem.equations)")

let samplemaths = Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz")
print("Instance physics is: \(samplemaths.physics)")
print("Instance formulae is: \(samplemaths.formulae)")

var chemCount = 0
var mathsCount = 0
for item in sa {
   if item is Chemistry {
      ++chemCount
   } else if item is Maths {
      ++mathsCount
   }
}

print("Subjects in chemistry contains \(chemCount) topics and maths contains \(mathsCount) topics")

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

Instance physics is: solid physics
Instance equation is: Hertz
Instance physics is: Fluid Dynamics
Instance formulae is: Giga Hertz
Subjects in chemistry contains 2 topics and maths contains 3 topics

Downcasting

Das Downcasting des Unterklassentyps kann mit zwei Operatoren (as? Und as!) Durchgeführt werden. 'As?' Gibt einen optionalen Wert zurück, wenn der Wert Null zurückgibt. Es wird verwendet, um den erfolgreichen Downcast zu überprüfen.

'wie!' Gibt das erzwungene Entpacken zurück, wie in der optionalen Verkettung beschrieben, wenn das Downcasting den Wert Null zurückgibt. Es wird verwendet, um einen Laufzeitfehler im Falle eines Downcast-Fehlers auszulösen

class Subjects {
   var physics: String
   init(physics: String) {
      self.physics = physics
   }
}

class Chemistry: Subjects {
   var equations: String
   init(physics: String, equations: String) {
      self.equations = equations
      super.init(physics: physics)
   }
}

class Maths: Subjects {
   var formulae: String
   init(physics: String, formulae: String) {
      self.formulae = formulae
      super.init(physics: physics)
   }
}

let sa = [
   Chemistry(physics: "solid physics", equations: "Hertz"),
   Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz"),
   Chemistry(physics: "Thermo physics", equations: "Decibels"),
   Maths(physics: "Astro Physics", formulae: "MegaHertz"),
   Maths(physics: "Differential Equations", formulae: "Cosine Series")]

let samplechem = Chemistry(physics: "solid physics", equations: "Hertz")
print("Instance physics is: \(samplechem.physics)")
print("Instance equation is: \(samplechem.equations)")

let samplemaths = Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz")
print("Instance physics is: \(samplemaths.physics)")
print("Instance formulae is: \(samplemaths.formulae)")

var chemCount = 0
var mathsCount = 0

for item in sa {
   if let print = item as? Chemistry {
      print("Chemistry topics are: '\(print.physics)', \(print.equations)")
   } else if let example = item as? Maths {
      print("Maths topics are: '\(example.physics)', \(example.formulae)")
   }
}

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

Instance physics is: solid physics
Instance equation is: Hertz
Instance physics is: Fluid Dynamics
Instance formulae is: Giga Hertz
Chemistry topics are: 'solid physics', Hertz
Maths topics are: 'Fluid Dynamics', Giga Hertz
Chemistry topics are: 'Thermo physics', Decibels
Maths topics are: 'Astro Physics', MegaHertz
Maths topics are: 'Differential Equations', Cosine Series

Typografie: Beliebiges Objekt

Das Schlüsselwort 'Any' wird verwendet, um eine Instanz darzustellen, die zu einem beliebigen Typ gehört, einschließlich Funktionstypen.

class Subjects {
   var physics: String
   init(physics: String) {
      self.physics = physics
   }
}

class Chemistry: Subjects {
   var equations: String
   init(physics: String, equations: String) {
      self.equations = equations
      super.init(physics: physics)
   }
}

class Maths: Subjects {
   var formulae: String
   init(physics: String, formulae: String) {
      self.formulae = formulae
      super.init(physics: physics)
   }
}

let sa = [
   Chemistry(physics: "solid physics", equations: "Hertz"),
   Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz"),
   Chemistry(physics: "Thermo physics", equations: "Decibels"),
   Maths(physics: "Astro Physics", formulae: "MegaHertz"),
   Maths(physics: "Differential Equations", formulae: "Cosine Series")]

let samplechem = Chemistry(physics: "solid physics", equations: "Hertz")
print("Instance physics is: \(samplechem.physics)")
print("Instance equation is: \(samplechem.equations)")

let samplemaths = Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz")
print("Instance physics is: \(samplemaths.physics)")
print("Instance formulae is: \(samplemaths.formulae)")

var chemCount = 0
var mathsCount = 0

for item in sa {
   if let print = item as? Chemistry {
      print("Chemistry topics are: '\(print.physics)', \(print.equations)")
   } else if let example = item as? Maths {
      print("Maths topics are: '\(example.physics)', \(example.formulae)")
   }
}

var exampleany = [Any]()

exampleany.append(12)
exampleany.append(3.14159)
exampleany.append("Example for Any")
exampleany.append(Chemistry(physics: "solid physics", equations: "Hertz"))

for print in exampleany {
   switch print {
      case let someInt as Int:
         print("Integer value is \(someInt)")
      case let someDouble as Double where someDouble > 0:
         print("Pi value is \(someDouble)")
      case let someString as String:
         print("\(someString)")
      case let phy as Chemistry:   
         print("Topics '\(phy.physics)', \(phy.equations)")
      default:
         print("None")
   }
}

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

Instance physics is: solid physics
Instance equation is: Hertz
Instance physics is: Fluid Dynamics
Instance formulae is: Giga Hertz
Chemistry topics are: 'solid physics', Hertz
Maths topics are: 'Fluid Dynamics', Giga Hertz
Chemistry topics are: 'Thermo physics', Decibels
Maths topics are: 'Astro Physics', MegaHertz
Maths topics are: 'Differential Equations', Cosine Series
Integer value is 12
Pi value is 3.14159
Example for Any
Topics 'solid physics', Hertz

AnyObject

Um die Instanz eines beliebigen Klassentyps darzustellen, wird das Schlüsselwort 'AnyObject' verwendet.

class Subjects {
   var physics: String
   init(physics: String) {
      self.physics = physics
   }
}

class Chemistry: Subjects {
   var equations: String
   init(physics: String, equations: String) {
      self.equations = equations
      super.init(physics: physics)
   }
}

class Maths: Subjects {
   var formulae: String
   init(physics: String, formulae: String) {
      self.formulae = formulae
      super.init(physics: physics)
   }
}

let saprint: [AnyObject] = [Chemistry(physics: "solid physics", equations: "Hertz"),
   Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz"),
   Chemistry(physics: "Thermo physics", equations: "Decibels"),
   Maths(physics: "Astro Physics", formulae: "MegaHertz"),
   Maths(physics: "Differential Equations", formulae: "Cosine Series")]

let samplechem = Chemistry(physics: "solid physics", equations: "Hertz")
print("Instance physics is: \(samplechem.physics)")
print("Instance equation is: \(samplechem.equations)")

let samplemaths = Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz")
print("Instance physics is: \(samplemaths.physics)")
print("Instance formulae is: \(samplemaths.formulae)")

var chemCount = 0
var mathsCount = 0

for item in saprint {
   if let print = item as? Chemistry {
      print("Chemistry topics are: '\(print.physics)', \(print.equations)")
   } else if let example = item as? Maths {
      print("Maths topics are: '\(example.physics)', \(example.formulae)")
   }
}

var exampleany = [Any]()
exampleany.append(12)
exampleany.append(3.14159)
exampleany.append("Example for Any")
exampleany.append(Chemistry(physics: "solid physics", equations: "Hertz"))

for print in exampleany {
   switch print {
      case let someInt as Int:
         print("Integer value is \(someInt)")
      case let someDouble as Double where someDouble > 0:
         print("Pi value is \(someDouble)")
      case let someString as String:
         print("\(someString)")
      case let phy as Chemistry:
         print("Topics '\(phy.physics)', \(phy.equations)")
      default:
         print("None")
   }
}

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

Instance physics is: solid physics
Instance equation is: Hertz
Instance physics is: Fluid Dynamics
Instance formulae is: Giga Hertz
Chemistry topics are: 'solid physics', Hertz
Maths topics are: 'Fluid Dynamics', Giga Hertz
Chemistry topics are: 'Thermo physics', Decibels
Maths topics are: 'Astro Physics', MegaHertz
Maths topics are: 'Differential Equations', Cosine Series
Integer value is 12
Pi value is 3.14159
Example for Any
Topics 'solid physics', Hertz

Die Funktionalität einer vorhandenen Klasse, Struktur oder eines Aufzählungstyps kann mithilfe von Erweiterungen hinzugefügt werden. Typfunktionalität kann mit Erweiterungen hinzugefügt werden, aber das Überschreiben der Funktionalität ist mit Erweiterungen nicht möglich.

Swift Extension Functionalities - -

  • Hinzufügen von berechneten Eigenschaften und berechneten Typeneigenschaften
  • Instanz- und Typmethoden definieren.
  • Bereitstellung neuer Initialisierer.
  • Indizes definieren
  • Definieren und Verwenden neuer verschachtelter Typen
  • Anpassen eines vorhandenen Typs an ein Protokoll

Erweiterungen werden mit dem Schlüsselwort 'extension' deklariert.

Syntax

extension SomeType {
   // new functionality can be added here
}

Bestehender Typ kann auch mit Erweiterungen hinzugefügt werden, um ihn als Protokollstandard zu verwenden, und seine Syntax ähnelt der von Klassen oder Strukturen.

extension SomeType: SomeProtocol, AnotherProtocol {
   // protocol requirements is described here
}

Berechnete Eigenschaften

Berechnete Eigenschaften 'Instanz' und 'Typ' können auch mit Hilfe von Erweiterungen erweitert werden.

extension Int {
   var add: Int {return self + 100 }
   var sub: Int { return self - 10 }
   var mul: Int { return self * 10 }
   var div: Int { return self / 5 }
}

let addition = 3.add
print("Addition is \(addition)")

let subtraction = 120.sub
print("Subtraction is \(subtraction)")

let multiplication = 39.mul
print("Multiplication is \(multiplication)")

let division = 55.div
print("Division is \(division)")

let mix = 30.add + 34.sub
print("Mixed Type is \(mix)")

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

Addition is 103
Subtraction is 110
Multiplication is 390
Division is 11
Mixed Type is 154

Initialisierer

Swift 4 bietet die Flexibilität, einem vorhandenen Typ durch Erweiterungen neue Initialisierer hinzuzufügen. Der Benutzer kann eigene benutzerdefinierte Typen hinzufügen, um die bereits definierten Typen zu erweitern. Zusätzliche Initialisierungsoptionen sind ebenfalls möglich. Erweiterungen unterstützen nur init (). deinit () wird von den Erweiterungen nicht unterstützt.

struct sum {
   var num1 = 100, num2 = 200
}

struct diff {
   var no1 = 200, no2 = 100
}

struct mult {
   var a = sum()
   var b = diff()
}

let calc = mult()
print ("Inside mult block \(calc.a.num1, calc.a.num2)")
print("Inside mult block \(calc.b.no1, calc.b.no2)")

let memcalc = mult(a: sum(num1: 300, num2: 500),b: diff(no1: 300, no2: 100))
print("Inside mult block \(memcalc.a.num1, memcalc.a.num2)")
print("Inside mult block \(memcalc.b.no1, memcalc.b.no2)")

extension mult {
   init(x: sum, y: diff) {
      let X = x.num1 + x.num2
      let Y = y.no1 + y.no2
   }
}

let a = sum(num1: 100, num2: 200)
print("Inside Sum Block:\( a.num1, a.num2)")

let b = diff(no1: 200, no2: 100)
print("Inside Diff Block: \(b.no1, b.no2)")

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

Inside mult block (100, 200)
Inside mult block (200, 100)
Inside mult block (300, 500)
Inside mult block (300, 100)
Inside Sum Block:(100, 200)
Inside Diff Block: (200, 100)

Methoden

Neue Instanzmethoden und Typmethoden können mit Hilfe von Erweiterungen weiter zur Unterklasse hinzugefügt werden.

extension Int {
   func topics(summation: () -> ()) {
      for _ in 0..<self {
         summation()
      }
   }
}

4.topics(summation: {
   print("Inside Extensions Block")
})

3.topics(summation: {
   print("Inside Type Casting Block")
})

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

Inside Extensions Block
Inside Extensions Block
Inside Extensions Block
Inside Extensions Block
Inside Type Casting Block
Inside Type Casting Block
Inside Type Casting Block

Die Funktion topic () verwendet ein Argument vom Typ '(Summation: () → ())', um anzugeben, dass die Funktion keine Argumente akzeptiert und keine Werte zurückgibt. Um diese Funktion mehrmals aufzurufen, wird for block initialisiert und der Aufruf der Methode mit topic () initialisiert.

Mutierende Instanzmethoden

Instanzmethoden können auch mutiert werden, wenn sie als Erweiterungen deklariert werden.

Struktur- und Aufzählungsmethoden, die sich selbst oder seine Eigenschaften ändern, müssen die Instanzmethode als mutierend markieren, genau wie Mutationsmethoden aus einer ursprünglichen Implementierung.

extension Double {
   mutating func square() {
      let pi = 3.1415
      self = pi * self * self
   }
}

var Trial1 = 3.3
Trial1.square()
print("Area of circle is: \(Trial1)")

var Trial2 = 5.8
Trial2.square()
print("Area of circle is: \(Trial2)")

var Trial3 = 120.3
Trial3.square()
print("Area of circle is: \(Trial3)")

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

Area of circle is: 34.210935
Area of circle is: 105.68006
Area of circle is: 45464.070735

Indizes

Das Hinzufügen neuer Indizes zu bereits deklarierten Instanzen kann auch mit Erweiterungen möglich sein.

extension Int {
   subscript(var multtable: Int) -> Int {
      var no1 = 1
      while multtable > 0 {
         no1 *= 10
         --multtable
      }
      return (self / no1) % 10
   }
}

print(12[0])
print(7869[1])
print(786543[2])

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

2
6
5

Verschachtelte Typen

Verschachtelte Typen für Klassen-, Struktur- und Aufzählungsinstanzen können auch mithilfe von Erweiterungen erweitert werden.

extension Int {
   enum calc {
      case add
      case sub
      case mult
      case div
      case anything
   }
   var print: calc {
      switch self {
         case 0:
            return .add
         case 1:
            return .sub
         case 2:
            return .mult
         case 3:
            return .div
         default:
            return .anything
      }
   }
}

func result(numb: [Int]) {
   for i in numb {
      switch i.print {
         case .add:
            print(" 10 ")
         case .sub:
            print(" 20 ")
         case .mult:
            print(" 30 ")
         case .div:
            print(" 40 ")
         default:
            print(" 50 ")
      }
   }
}
result(numb: [0, 1, 2, 3, 4, 7])

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

10
20
30
40
50
50

Protokolle bieten einen Entwurf für Methoden, Eigenschaften und andere Anforderungsfunktionen. Es wird lediglich als Methoden- oder Eigenschaftsskelett anstelle der Implementierung beschrieben. Die Implementierung von Methoden und Eigenschaften kann ferner durch Definieren von Klassen, Funktionen und Aufzählungen erfolgen. Die Konformität eines Protokolls ist definiert als die Methoden oder Eigenschaften, die die Anforderungen des Protokolls erfüllen.

Syntax

Protokolle folgen ebenfalls der ähnlichen Syntax wie Klassen, Strukturen und Aufzählungen -

protocol SomeProtocol {
   // protocol definition 
}

Protokolle werden nach den Namen der Klassen-, Struktur- oder Aufzählungstypen deklariert. Einzel- und Mehrfachprotokolldeklarationen sind ebenfalls möglich. Wenn mehrere Protokolle definiert sind, müssen diese durch Kommas getrennt werden.

struct SomeStructure: Protocol1, Protocol2 {
   // structure definition 
}

Wenn ein Protokoll für die Superklasse definiert werden muss, sollte der Protokollname dem Superklassennamen mit einem Komma folgen.

class SomeClass: SomeSuperclass, Protocol1, Protocol2 {
   // class definition 
}

Eigenschafts- und Methodenanforderungen

Das Protokoll wird verwendet, um eine bestimmte Klassentyp- oder Instanzeigenschaft anzugeben. Es wird nur der Typ oder die Instanzeigenschaft allein angegeben, anstatt anzugeben, ob es sich um eine gespeicherte oder eine berechnete Eigenschaft handelt. Außerdem wird angegeben, ob die Eigenschaft "gettable" oder "Settable" ist.

Eigenschaftsanforderungen werden durch das Schlüsselwort 'var' als Eigenschaftsvariablen deklariert. {get set} wird verwendet, um gettable- und Settable-Eigenschaften nach ihrer Typdeklaration zu deklarieren. Gettable wird von der Eigenschaft {get} nach ihrer Typdeklaration erwähnt.

protocol classa {
   var marks: Int { get set }
   var result: Bool { get }
   
   func attendance() -> String
   func markssecured() -> String
}

protocol classb: classa {
   var present: Bool { get set }
   var subject: String { get set }
   var stname: String { get set }
}

class classc: classb {
   var marks = 96
   let result = true
   var present = false
   var subject = "Swift 4 Protocols"
   var stname = "Protocols"

   func attendance() -> String {
      return "The \(stname) has secured 99% attendance"
   }
   func markssecured() -> String {
      return "\(stname) has scored \(marks)"
   }
}

let studdet = classc()
studdet.stname = "Swift 4"
studdet.marks = 98
studdet.markssecured()

print(studdet.marks)
print(studdet.result)
print(studdet.present)
print(studdet.subject)
print(studdet.stname)

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

98
true
false
Swift 4 Protocols
Swift 4

Anforderungen an die Mutationsmethode

protocol daysofaweek {
   mutating func print()
}

enum days: daysofaweek {
   case sun, mon, tue, wed, thurs, fri, sat 
   mutating func print() {
      switch self {
         case sun:
            self = sun
            print("Sunday")
         case mon:
            self = mon
            print("Monday")
         case tue:
            self = tue
            print("Tuesday")
         case wed:
            self = wed
            print("Wednesday")
         case mon:
            self = thurs
            print("Thursday")
         case tue:
            self = fri
            print("Friday")
         case sat:
            self = sat
            print("Saturday")
         default:
            print("NO Such Day")
      }
   }
}

var res = days.wed
res.print()

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

Wednesday

Initialisierungsanforderungen

Mit Swing kann der Benutzer Protokolle initialisieren, um der Typkonformität zu folgen, die der von normalen Initialisierern ähnelt.

Syntax

protocol SomeProtocol {
   init(someParameter: Int)
}

Zum Beispiel

protocol tcpprotocol {
   init(aprot: Int)
}

Klassenimplementierungen von Protokollinitialisierungsanforderungen

Der Designated- oder Convenience-Initialisierer ermöglicht es dem Benutzer, ein Protokoll so zu initialisieren, dass es seinem Standard mit dem reservierten Schlüsselwort 'erforderlich' entspricht.

class SomeClass: SomeProtocol {
   required init(someParameter: Int) {
      // initializer implementation statements
   }
}

protocol tcpprotocol {
   init(aprot: Int)
}

class tcpClass: tcpprotocol {
   required init(aprot: Int) {
   }
}

Die Protokollkonformität wird für alle Unterklassen für die explizite oder vererbte Implementierung durch den Modifikator 'erforderlich' sichergestellt.

Wenn eine Unterklasse ihre Initialisierungsanforderung für die Superklasse überschreibt, wird sie durch das Modifikatorschlüsselwort 'override' angegeben.

protocol tcpprotocol {
   init(no1: Int)
}

class mainClass {
   var no1: Int        // local storage
   init(no1: Int) {
      self.no1 = no1  // initialization
   }
}

class subClass: mainClass, tcpprotocol {
   var no2: Int
   init(no1: Int, no2 : Int) {
      self.no2 = no2
      super.init(no1:no1)
   }
   // Requires only one parameter for convenient method
   required override convenience init(no1: Int) {
      self.init(no1:no1, no2:0)
   }
}

let res = mainClass(no1: 20)
let print = subClass(no1: 30, no2: 50)

print("res is: \(res.no1)")
print("res is: \(print.no1)")
print("res is: \(print.no2)")

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

res is: 20
res is: 30
res is: 50

Protokolle als Typen

Anstatt Funktionen in einem Protokoll zu implementieren, werden sie als Typen für Funktionen, Klassen, Methoden usw. verwendet.

Auf Protokolle kann als Typ in - zugegriffen werden

  • Funktion, Methode oder Initialisierung als Parameter oder Rückgabetyp

  • Konstante, Variable oder Eigenschaft

  • Arrays, Wörterbücher oder andere Container als Elemente

protocol Generator {
   typealias members
   func next() -> members?
}

var items = [10,20,30].generate()
while let x = items.next() {
   print(x)
}

for lists in map([1,2,3], {i in i*5}) {
   print(lists)
}

print([100,200,300])
print(map([1,2,3], {i in i*10}))

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

10
20
30
5
10
15
[100, 200, 300]
[10, 20, 30]

Hinzufügen der Protokollkonformität mit einer Erweiterung

Bestehende Typen können mithilfe von Erweiterungen übernommen und an ein neues Protokoll angepasst werden. Neue Eigenschaften, Methoden und Indizes können mithilfe von Erweiterungen zu vorhandenen Typen hinzugefügt werden.

protocol AgeClasificationProtocol {
   var age: Int { get }
   func agetype() -> String
}
class Person {
   let firstname: String
   let lastname: String
   var age: Int
   
   init(firstname: String, lastname: String) {
      self.firstname = firstname
      self.lastname = lastname
      self.age = 10
   }
}

extension Person : AgeClasificationProtocol {
   func fullname() -> String {
      var c: String
      c = firstname + " " + lastname
      return c
   }
   func agetype() -> String {
      switch age {
         case 0...2:
            return "Baby"
         case 2...12:
            return "Child"
         case 13...19:
            return "Teenager"
         case let x where x > 65:
            return "Elderly"
         default:
            return "Normal"
      }
   }
}

Protokollvererbung

Mit Swift 4 können Protokolle Eigenschaften von ihren definierten Eigenschaften erben. Es ähnelt dem der Klassenvererbung, bietet jedoch die Möglichkeit, mehrere durch Kommas getrennte geerbte Protokolle aufzulisten.

protocol classa {
   var no1: Int { get set }
   func calc(sum: Int)
}
protocol result {
   func print(target: classa)
}
class student2: result {
   func print(target: classa) {
      target.calc(sum: 1)
   }
}
class classb: result {
   func print(target: classa) {
      target.calc(sum: 5)
   }
}

class student: classa {
   var no1: Int = 10
   
   func calc(sum: Int) {
      no1 -= sum
      print("Student attempted \(sum) times to pass")
         
      if no1 <= 0 {
         print("Student is absent for exam")
      }
   }
}

class Player {
   var stmark: result!

   init(stmark: result) {
      self.stmark = stmark
   }
   func print(target: classa) {
      stmark.print(target: target)
   }
}

var marks = Player(stmark: student2())
var marksec = student()

marks.print(target: marksec)
marks.print(target: marksec)
marks.print(target: marksec)
marks.stmark = classb()
marks.print(target: marksec)
marks.print(target: marksec)
marks.print(target: marksec)

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

Student attempted 1 times to pass
Student attempted 1 times to pass
Student attempted 1 times to pass
Student attempted 5 times to pass
Student attempted 5 times to pass
Student is absent for exam
Student attempted 5 times to pass
Student is absent for exam

Nur-Klasse-Protokolle

Wenn Protokolle definiert sind und der Benutzer ein Protokoll mit Klassen definieren möchte, sollte es hinzugefügt werden, indem zuerst die Klasse definiert wird, gefolgt von der Vererbungsliste des Protokolls.

protocol tcpprotocol {
   init(no1: Int)
}
class mainClass {
   var no1: Int        // local storage
   init(no1: Int) {
      self.no1 = no1  // initialization
   }
}
class subClass: mainClass, tcpprotocol {
   var no2: Int
   init(no1: Int, no2 : Int) {
      self.no2 = no2
      super.init(no1:no1)
   }
   
   // Requires only one parameter for convenient method
   required override convenience init(no1: Int) {
      self.init(no1:no1, no2:0)
   }
}

let res = mainClass(no1: 20)
let print = subClass(no1: 30, no2: 50)

print("res is: \(res.no1)")
print("res is: \(print.no1)")
print("res is: \(print.no2)")

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

res is: 20
res is: 30
res is: 50

Protokollzusammensetzung

Mit Swift 4 können mithilfe der Protokollzusammensetzung mehrere Protokolle gleichzeitig aufgerufen werden.

Syntax

protocol<SomeProtocol, AnotherProtocol>

Beispiel

protocol stname {
   var name: String { get }
}
protocol stage {
   var age: Int { get }
}
struct Person: stname, stage {
   var name: String
   var age: Int
}
func print(celebrator: stname & stage) {
   print("\(celebrator.name) is \(celebrator.age) years old")
}
let studname = Person(name: "Priya", age: 21)
print(studname)

let stud = Person(name: "Rehan", age: 29)
print(stud)

let student = Person(name: "Roshan", age: 19)
print(student)

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

Person(name: "Priya", age: 21)
Person(name: "Rehan", age: 29)
Person(name: "Roshan", age: 19)

Überprüfen der Protokollkonformität

Die Protokollkonformität wird von 'is' und 'as' Operatoren getestet, die denen des Typgusses ähnlich sind.

  • Der Operator is gibt true zurück, wenn eine Instanz dem Protokollstandard entspricht, und false, wenn dies fehlschlägt.

  • Das as? Die Version des Downcast-Operators gibt einen optionalen Wert des Protokolltyps zurück. Dieser Wert ist Null, wenn die Instanz nicht diesem Protokoll entspricht.

  • Die as-Version des Downcast-Operators erzwingt den Downcast auf den Protokolltyp und löst einen Laufzeitfehler aus, wenn der Downcast nicht erfolgreich ist.

import Foundation

@objc protocol rectangle {
   var area: Double { get }
}
@objc class Circle: rectangle {
   let pi = 3.1415927
   var radius: Double
   var area: Double { return pi * radius * radius }
   init(radius: Double) { self.radius = radius }
}
@objc class result: rectangle {
   var area: Double
   init(area: Double) { self.area = area }
}
class sides {
   var rectsides: Int
   init(rectsides: Int) { self.rectsides = rectsides }
}
let objects: [AnyObject] = [Circle(radius: 2.0),result(area:198),sides(rectsides: 4)]

for object in objects {
   if let objectWithArea = object as? rectangle {
      print("Area is \(objectWithArea.area)")
   } else {
      print("Rectangle area is not defined")
   }
}

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

Area is 12.5663708
Area is 198.0
Rectangle area is not defined

Die Sprache Swift 4 bietet allgemeine Funktionen zum Schreiben flexibler und wiederverwendbarer Funktionen und Typen. Generika werden verwendet, um Doppelarbeit zu vermeiden und Abstraktion bereitzustellen. Swift 4-Standardbibliotheken werden mit generischem Code erstellt. Swift 4s-Typen 'Arrays' und 'Dictionary' gehören zu generischen Sammlungen. Mit Hilfe von Arrays und Wörterbüchern werden die Arrays so definiert, dass sie 'Int'-Werte und' String'-Werte oder andere Typen enthalten.

func exchange(a: inout Int, b: inout Int) {
   let temp = a
   a = b
   b = temp
}

var numb1 = 100
var numb2 = 200

print("Before Swapping values are: \(numb1) and \(numb2)")
exchange(a: &numb1, b: &numb2)
print("After Swapping values are: \(numb1) and \(numb2)")

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

Before Swapping values are: 100 and 200
After Swapping values are: 200 and 100

Allgemeine Funktionen: Typparameter

Generische Funktionen können verwendet werden, um auf jeden Datentyp wie 'Int' oder 'String' zuzugreifen.

func exchange<T>(a: inout T, b: inout T) {
   let temp = a
   a = b
   b = temp
}
var numb1 = 100
var numb2 = 200

print("Before Swapping Int values are: \(numb1) and \(numb2)")
exchange(a: &numb1, b: &numb2)
print("After Swapping Int values are: \(numb1) and \(numb2)")

var str1 = "Generics"
var str2 = "Functions"

print("Before Swapping String values are: \(str1) and \(str2)")
exchange(a: &str1, b: &str2)
print("After Swapping String values are: \(str1) and \(str2)")

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

Before Swapping Int values are: 100 and 200
After Swapping Int values are: 200 and 100
Before Swapping String values are: Generics and Functions
After Swapping String values are: Functions and Generics

Der Funktionsaustausch () wird verwendet, um Werte auszutauschen, was im obigen Programm beschrieben ist, und <T> wird als Typparameter verwendet. Zum ersten Mal wird function exchange () aufgerufen, um 'Int'-Werte zurückzugeben, und beim zweiten Aufruf von function exchange () werden' String'-Werte zurückgegeben. In die durch Kommas getrennten spitzen Klammern können mehrere Parametertypen eingefügt werden.

Typparameter werden als benutzerdefiniert bezeichnet, um den Zweck des darin enthaltenen Typparameters zu kennen. Swift 4 bietet <T> als generischen Typparameternamen. Typparameter wie Arrays und Wörterbücher können jedoch auch als Schlüsselwert benannt werden, um zu identifizieren, dass sie zum Typ 'Wörterbuch' gehören.

struct TOS<T> {
   var items = [T]()
   mutating func push(item: T) {
      items.append(item)
   }
   mutating func pop() -> T {
      return items.removeLast()
   }
}

var tos = TOS<String>()
tos.push(item: "Swift 4")
print(tos.items)

tos.push(item: "Generics")
print(tos.items)

tos.push(item: "Type Parameters")
print(tos.items)

tos.push(item: "Naming Type Parameters")
print(tos.items)

let deletetos = tos.pop()

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

[Swift 4]
[Swift 4, Generics]
[Swift 4, Generics, Type Parameters]
[Swift 4, Generics, Type Parameters, Naming Type Parameters]

Erweitern eines generischen Typs

Das Erweitern der Stack-Eigenschaft, um den oberen Rand des Elements zu ermitteln, ist im Schlüsselwort 'extension' enthalten.

struct TOS<T> {
   var items = [T]()
   mutating func push(item: T) {
      items.append(item)
   }
   mutating func pop() -> T {
      return items.removeLast()
   }
}
var tos = TOS<String>()
tos.push(item: "Swift 4")
print(tos.items)

tos.push(item: "Generics")
print(tos.items)

tos.push(item: "Type Parameters")
print(tos.items)

tos.push(item: "Naming Type Parameters")
print(tos.items)

extension TOS {
   var first: T? {
      return items.isEmpty ? nil : items[items.count - 1]
   }
}
if let first = tos.first {
   print("The top item on the stack is \(first).")
}

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

["Swift 4"]
["Swift 4", "Generics"]
["Swift 4", "Generics", "Type Parameters"]
["Swift 4", "Generics", "Type Parameters", "Naming Type Parameters"]
The top item on the stack is Naming Type Parameters.

Geben Sie Einschränkungen ein

In der Sprache Swift 4 können 'Typeinschränkungen' angeben, ob der Typparameter von einer bestimmten Klasse erbt, oder den Protokollkonformitätsstandard sicherstellen.

func exchange<T>(a: inout T, b: inout T) {
   let temp = a
   a = b
   b = temp
}
var numb1 = 100
var numb2 = 200

print("Before Swapping Int values are: \(numb1) and \(numb2)")
exchange(a: &numb1, b: &numb2)
print("After Swapping Int values are: \(numb1) and \(numb2)")

var str1 = "Generics"
var str2 = "Functions"

print("Before Swapping String values are: \(str1) and \(str2)")
exchange(a: &str1, b: &str2)
print("After Swapping String values are: \(str1) and \(str2)")

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

Before Swapping Int values are: 100 and 200
After Swapping Int values are: 200 and 100
Before Swapping String values are: Generics and Functions
After Swapping String values are: Functions and Generics

Zugehörige Typen

Mit Swift 4 können zugeordnete Typen innerhalb der Protokolldefinition mit dem Schlüsselwort 'Associatedtype' deklariert werden.

protocol Container {
   associatedtype ItemType
   mutating func append(item: ItemType)
   var count: Int { get }
   subscript(i: Int) -> ItemType { get }
}
struct TOS<T>: Container {
   // original Stack<T> implementation
   var items = [T]()
   mutating func push(item: T) {
      items.append(item)
   }
   mutating func pop() -> T {
      return items.removeLast()
   }
   
   // conformance to the Container protocol
   mutating func append(item: T) {
      self.push(item: item)
   }
   var count: Int {
      return items.count
   }
   subscript(i: Int) -> T {
      return items[i]
   }
}
var tos = TOS<String>()
tos.push(item: "Swift 4")
print(tos.items)

tos.push(item: "Generics")
print(tos.items)

tos.push(item: "Type Parameters")
print(tos.items)

tos.push(item: "Naming Type Parameters")
print(tos.items)

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

[Swift 4]
[Swift 4, Generics]
[Swift 4, Generics, Type Parameters]
[Swift 4, Generics, Type Parameters, Naming Type Parameters]

Where-Klauseln

Mithilfe von Typeinschränkungen kann der Benutzer Anforderungen an die Typparameter definieren, die einer generischen Funktion oder einem generischen Typ zugeordnet sind. Zum Definieren von Anforderungen für zugeordnete Typen 'where'-Klauseln werden als Teil der Typparameterliste deklariert. Das Schlüsselwort 'where' wird unmittelbar nach der Liste der Typparameter platziert, gefolgt von Einschränkungen der zugeordneten Typen, Gleichheitsbeziehungen zwischen Typen und zugeordneten Typen.

protocol Container {
   associatedtype ItemType
   mutating func append(item: ItemType)
   var count: Int { get }
   subscript(i: Int) -> ItemType { get }
}
struct Stack<T>: Container {
   // original Stack<T> implementation
   var items = [T]()
   mutating func push(item: T) {
      items.append(item)
   }
   mutating func pop() -> T {
      return items.removeLast()
   }

   // conformance to the Container protocol
   mutating func append(item: T) {
      self.push(item: item)
   }
   var count: Int {
      return items.count
   }
   subscript(i: Int) -> T {
      return items[i]
   }
}
func allItemsMatch<
C1: Container, C2: Container
where C1.ItemType == C2.ItemType, C1.ItemType: Equatable>
(someContainer: C1, anotherContainer: C2) -> Bool {
   // check that both containers contain the same number of items
   if someContainer.count != anotherContainer.count {
      return false
   }
   
   // check each pair of items to see if they are equivalent
   for i in 0..<someContainer.count {
      if someContainer[i] != anotherContainer[i] {
         return false
      }
   }
   // all items match, so return true
   return true
}  
var tos = Stack<String>()

tos.push(item: "Swift 4")
print(tos.items)

tos.push(item: "Generics")
print(tos.items)

tos.push(item: "Where Clause")
print(tos.items)

var eos = ["Swift 4", "Generics", "Where Clause"]
print(eos)

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

[Swift 4]
[Swift 4, Generics]
[Swift 4, Generics, Where Clause]
[Swift 4, Generics, Where Clause]

Um den Zugriff auf Codeblöcke, Module und Abstraktionen einzuschränken, erfolgt die Zugriffssteuerung. Auf Klassen, Strukturen und Aufzählungen kann über ihre Eigenschaften, Methoden, Initialisierer und Indizes über Zugriffssteuerungsmechanismen zugegriffen werden. Konstanten, Variablen und Funktionen in einem Protokoll sind eingeschränkt und ermöglichen den Zugriff als global und lokal durch Zugriffssteuerung. Die auf Eigenschaften, Typen und Funktionen angewendete Zugriffssteuerung kann als "Entitäten" bezeichnet werden.

Das Zugriffssteuerungsmodell basiert auf Modulen und Quelldateien.

Das Modul ist als einzelne Einheit der Codeverteilung definiert und kann mit dem Schlüsselwort 'import' importiert werden. Eine Quelldatei wird als einzelne Quellcodedatei in einem Modul definiert, um auf mehrere Typen und Funktionen zuzugreifen.

Die Sprache Swift 4 bietet drei verschiedene Zugriffsebenen. Sie sind öffentlich, intern und privat zugänglich.

S.No. Zugriffsebenen & Definition
1

Public

Ermöglicht die Verarbeitung von Entitäten in einer beliebigen Quelldatei aus ihrem definierenden Modul, einer Quelldatei aus einem anderen Modul, das das definierende Modul importiert.

2

Internal

Ermöglicht die Verwendung von Entitäten in einer Quelldatei aus ihrem definierenden Modul, jedoch nicht in einer Quelldatei außerhalb dieses Moduls.

3

Private

Beschränkt die Verwendung einer Entität auf die eigene definierende Quelldatei. Der private Zugriff spielt eine Rolle, um die Implementierungsdetails einer bestimmten Codefunktionalität auszublenden.

Syntax

public class SomePublicClass {}
internal class SomeInternalClass {}
private class SomePrivateClass {}

public var somePublicVariable = 0
internal let someInternalConstant = 0
private func somePrivateFunction() {}

Zugriffskontrolle für Funktionstypen

Bei einigen Funktionen sind möglicherweise Argumente innerhalb der Funktion ohne Rückgabewerte deklariert. Das folgende Programm deklariert a und b als Argumente für die Funktion sum (). Innerhalb der Funktion selbst werden die Werte für die Argumente a und b durch Aufrufen des Funktionsaufrufs sum () übergeben und ihre Werte gedruckt, wodurch Rückgabewerte eliminiert werden. Um den Rückgabetyp der Funktion als privat festzulegen, deklarieren Sie die allgemeine Zugriffsebene der Funktion mit dem Modifikator private.

private func sum(a: Int, b: Int) {
   let a = a + b
   let b = a - b
   print(a, b)
}

sum(a: 20, b: 10)
sum(a: 40, b: 10)
sum(a: 24, b: 6)

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

30 20
50 40
30 24

Zugriffssteuerung für Aufzählungstypen

public enum Student {
   case Name(String)
   case Mark(Int,Int,Int)
}
var studDetails = Student.Name("Swift 4")
var studMarks = Student.Mark(98,97,95)

switch studMarks {
   case .Name(let studName):
      print("Student name is: \(studName).")
   case .Mark(let Mark1, let Mark2, let Mark3):
      print("Student Marks are: \(Mark1),\(Mark2),\(Mark3).")
   
}

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

Student Marks are: 98,97,95

Die Aufzählung in der Sprache Swift 4 erhält für einzelne Fälle einer Aufzählung automatisch dieselbe Zugriffsebene. Betrachten Sie zum Beispiel den Zugriff auf den Schülernamen und die in drei Fächern gesicherten Noten. Der Aufzählungsname wird als Schüler deklariert, und die in der Aufzählungsklasse vorhandenen Mitglieder sind Namen, die zum Zeichenfolgendatentyp gehören. Noten werden als Marke1, Marke2 und Marke3 des Datentyps Integer dargestellt. Zugriff auf den Namen des Schülers oder auf die von ihm erzielten Noten. Jetzt druckt der Switch-Fall den Schülernamen, wenn dieser Fallblock ausgeführt wird, andernfalls werden die vom Schüler gesicherten Markierungen gedruckt. Wenn beide Bedingungen fehlschlagen, wird der Standardblock ausgeführt.

Zugriffskontrolle für Unterklassen

Mit Swift 4 kann der Benutzer jede Klasse unterordnen, auf die im aktuellen Zugriffskontext zugegriffen werden kann. Eine Unterklasse kann keine höhere Zugriffsebene als ihre Oberklasse haben. Der Benutzer darf keine öffentliche Unterklasse einer internen Oberklasse schreiben.

public class cricket {
   internal func printIt() {
      print("Welcome to Swift 4 Super Class")
   }
}

internal class tennis: cricket {
   override internal func printIt() {
      print("Welcome to Swift 4 Sub Class")
   }
}

let cricinstance = cricket()
cricinstance.printIt()

let tennisinstance = tennis()
tennisinstance.printIt()

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

Welcome to Swift Super Class
Welcome to Swift Sub Class

Zugriffssteuerung für Konstanten, Variablen, Eigenschaften und Indizes

Swift 4-Konstante, -Variable oder -Eigenschaft kann nicht als öffentlicher Typ definiert werden. Es ist nicht gültig, eine öffentliche Eigenschaft mit einem privaten Typ zu schreiben. Ebenso kann ein Index nicht öffentlicher sein als sein Index- oder Rückgabetyp.

Wenn eine Konstante, Variable, Eigenschaft oder ein Index einen privaten Typ verwendet, muss die Konstante, Variable, Eigenschaft oder der Index ebenfalls als privat markiert werden.

private var privateInstance = SomePrivateClass()

Getter und Setter

Getter und Setter für Konstanten, Variablen, Eigenschaften und Indizes erhalten automatisch dieselbe Zugriffsebene wie die Konstanten, Variablen, Eigenschaften oder Indizes, zu denen sie gehören.

class Samplepgm {
   var counter: Int = 0{
      willSet(newTotal) {
         print("Total Counter is: \(newTotal)")
      }
      didSet {
         if counter > oldValue {
            print("Newly Added Counter \(counter - oldValue)")
         }
      }
   }
}

let NewCounter = Samplepgm()
NewCounter.counter = 100
NewCounter.counter = 800

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

Total Counter is: 100
Newly Added Counter 100
Total Counter is: 800
Newly Added Counter 700

Zugriffssteuerung für Initialisierer und Standardinitialisierer

Benutzerdefinierte Initialisierer können einer Zugriffsebene zugewiesen werden, die kleiner oder gleich dem Typ ist, den sie initialisieren. Ein erforderlicher Initialisierer muss dieselbe Zugriffsebene haben wie die Klasse, zu der er gehört. Die Typen der Parameter eines Initialisierers können nicht privater sein als die Zugriffsebene des Initialisierers.

Um jede Unterklasse des Schlüsselworts 'Initialisieren' erforderlich zu deklarieren, muss vor der Funktion init () definiert werden.

class classA {
   required init() {
      let a = 10
      print(a)
   }
}
class classB: classA {
   required init() {
      let b = 30
      print(b)
   }
}
let res = classA()
let print = classB()

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

10
30
10

Ein Standardinitialisierer hat dieselbe Zugriffsebene wie der Typ, den er initialisiert, es sei denn, dieser Typ ist als öffentlich definiert. Wenn die Standardinitialisierung als öffentlich definiert ist, wird sie als intern betrachtet. Wenn der Benutzer einen öffentlichen Typ benötigt, der mit einem Initialisierer ohne Argumente in einem anderen Modul initialisiert werden kann, geben Sie explizit einen öffentlichen Initialisierer ohne Argumente als Teil der Typdefinition an.

Zugriffskontrolle für Protokolle

Wenn wir ein neues Protokoll definieren, um Funktionen von einem vorhandenen Protokoll zu erben, müssen beide dieselben Zugriffsebenen deklariert werden, um die Eigenschaften voneinander zu erben. Mit der Swift 4-Zugriffskontrolle können die Benutzer kein "öffentliches" Protokoll definieren, das von einem "internen" Protokoll erbt.

public protocol tcpprotocol {
   init(no1: Int)
}
public class mainClass {
   var no1: Int      // local storage
   init(no1: Int) {
      self.no1 = no1 // initialization
   }
}
class subClass: mainClass, tcpprotocol {
   var no2: Int
   init(no1: Int, no2 : Int) {
      self.no2 = no2
      super.init(no1:no1)
   }
   
   // Requires only one parameter for convenient method
   required override convenience init(no1: Int) {
      self.init(no1:no1, no2:0)
   }
}

let res = mainClass(no1: 20)
let print = subClass(no1: 30, no2: 50)

print("res is: \(res.no1)")
print("res is: \(print.no1)")
print("res is: \(print.no2)")

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

res is: 20
res is: 30
res is: 50

Zugriffskontrolle für Erweiterungen

In Swift 4 können die Benutzer keinen expliziten Zugriffsebenenmodifikator für eine Erweiterung angeben, wenn der Benutzer diese Erweiterung verwendet, um die Protokollkonformität hinzuzufügen. Die Standardzugriffsebene für jede Implementierung der Protokollanforderungen innerhalb der Erweiterung wird mit einer eigenen Protokollzugriffsebene bereitgestellt.

Zugriffskontrolle für Generika

Mit Generika kann der Benutzer Mindestzugriffsebenen angeben, um auf die Typbeschränkungen für seine Typparameter zuzugreifen.

public struct TOS<T> {
   var items = [T]()
   mutating func push(item: T) {
      items.append(item)
   }
   mutating func pop() -> T {
      return items.removeLast()
   }
}

var tos = TOS<String>()
tos.push(item: "Swift 4")
print(tos.items)

tos.push(item: "Generics")
print(tos.items)

tos.push(item: "Type Parameters")
print(tos.items)

tos.push(item: "Naming Type Parameters")
print(tos.items)
let deletetos = tos.pop()

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

[Swift 4]
[Swift 4, Generics]
[Swift 4, Generics, Type Parameters]
[Swift 4, Generics, Type Parameters, Naming Type Parameters]

Zugriffskontrolle für Typ-Aliase

Der Benutzer kann Typaliasnamen definieren, um unterschiedliche Zugriffssteuerungstypen zu behandeln. Gleiche Zugriffsebene oder unterschiedliche Zugriffsebenen können vom Benutzer definiert werden. Wenn der Typalias "privat" ist, können die zugehörigen Mitglieder als "privat, intern vom öffentlichen Typ" deklariert werden. Wenn der Typalias öffentlich ist, können die Mitglieder kein Alias ​​als "interner" oder "privater" Name sein

Alle von Ihnen definierten Typ-Aliase werden zum Zwecke der Zugriffskontrolle als unterschiedliche Typen behandelt. Ein Typalias kann eine Zugriffsebene haben, die kleiner oder gleich der Zugriffsebene des Typs ist, den er aliasiert. Beispielsweise kann ein Alias ​​vom privaten Typ einen privaten, internen oder öffentlichen Typ aliasen, ein öffentlicher Alias ​​kann jedoch keinen internen oder privaten Typ aliasen.

public protocol Container {
   associatedtype ItemType
   mutating func append(item: ItemType)
   var count: Int { get }
   subscript(i: Int) -> ItemType { get }
}
struct Stack<T>: Container {
   // original Stack<T> implementation
   var items = [T]()
   mutating func push(item: T) {
      items.append(item)
   }
   mutating func pop() -> T {
      return items.removeLast()
   }
   
   // conformance to the Container protocol
   mutating func append(item: T) {
      self.push(item: item)
   }
   var count: Int {
      return items.count
   }
   subscript(i: Int) -> T {
      return items[i]
   }
}
func allItemsMatch<
   C1: Container, C2: Container
   where C1.ItemType == C2.ItemType, C1.ItemType: Equatable>
   (someContainer: C1, anotherContainer: C2) -> Bool {
   
   // check that both containers contain the same number of items
   if someContainer.count != anotherContainer.count {
      return false
   }
   
   // check each pair of items to see if they are equivalent
   for i in 0..<someContainer.count {
      if someContainer[i] != anotherContainer[i] {
         return false
      }
   }
   // all items match, so return true
   return true
}
var tos = Stack<String>()
tos.push(item: "Swift 4")
print(tos.items)

tos.push(item: "Generics")
print(tos.items)

tos.push(item: "Where Clause")
print(tos.items)

var eos = ["Swift 4", "Generics", "Where Clause"]
print(eos)

Wenn wir das obige Programm auf einem Spielplatz ausführen, erhalten wir das folgende Ergebnis:

[Swift 4]
[Swift 4, Generics]
[Swift 4, Generics, Where Clause]
[Swift 4, Generics, Where Clause]

Schnelle Kodierung und Dekodierung

Swift 4 stellt eine neue vor Codable Protokoll, mit dem Sie benutzerdefinierte Datentypen serialisieren und de-serialisieren können, ohne einen speziellen Code zu schreiben - und ohne sich Gedanken über den Verlust Ihrer Werttypen machen zu müssen.

struct Language: Codable {
   var name: String
   var version: Int
}
let swift = Language(name: "Swift", version: 4)
let java = Language(name: "java", version: 8)
let R = Language(name: "R", version: 3

Beachten Sie, dass Langauage dem codierbaren Protokoll entspricht. Jetzt konvertieren wir es mit einer einfachen Zeile in eine Json-Datendarstellung.

let encoder = JSONEncoder()
if let encoded = try? encoder.encode(java) {
   //Perform some operations on this value.
}

Swift codiert automatisch alle Werte in Ihrem Datentyp.

Sie können die Daten mit der Decoder-Funktion wie decodieren

let decoder = JSONDecoder()
if let decoded = try? decoder.decode(Language.self, from: encoded) {
   //Perform some operations on this value.
}

Sowohl JSONEncoder als auch das Gegenstück zur Eigenschaftsliste PropertyListEncoder bieten zahlreiche Optionen zum Anpassen ihrer Funktionsweise.