Swift - Guida rapida

Swift 4 è un nuovo linguaggio di programmazione sviluppato da Apple Inc per lo sviluppo di iOS e OS X. Swift 4 adotta il meglio di C e Objective-C, senza i vincoli della compatibilità C.

  • Swift 4 fa uso di schemi di programmazione sicuri.

  • Swift 4 fornisce moderne funzionalità di programmazione.

  • Swift 4 fornisce una sintassi simile a Objective-C.

  • Swift 4 è un modo fantastico per scrivere app iOS e OS X.

  • Swift 4 fornisce un accesso diretto ai framework Cocoa esistenti.

  • Swift 4 unifica le parti procedurali e orientate agli oggetti del linguaggio.

  • Swift 4 non necessita di un'importazione di libreria separata per supportare funzionalità come input / output o gestione delle stringhe.

Swift 4 utilizza lo stesso runtime del sistema Obj-C esistente su Mac OS e iOS, il che consente ai programmi Swift 4 di funzionare su molte piattaforme iOS 6 e OS X 10.8 esistenti.

Swift 4 è dotato di funzionalità playground in cui i programmatori di Swift 4 possono scrivere il loro codice ed eseguirlo per vedere immediatamente i risultati.

La prima versione pubblica di Swift è stata rilasciata nel 2010. Ci sono voluti Chris LattnerSono passati quasi 14 anni dalla prima versione ufficiale e, successivamente, è stata supportata da molti altri contributori. Swift 4 è stato incluso in Xcode 6 beta.

I progettisti Swift hanno preso idee da vari altri linguaggi popolari come Objective-C, Rust, Haskell, Ruby, Python, C # e CLU.

Configurazione dell'ambiente locale

Swift 4 fornisce una piattaforma Playground per scopi di apprendimento e configureremo la stessa. È necessario il software xCode per avviare la codifica di Swift 4 in Playground. Una volta che hai acquisito dimestichezza con i concetti di Swift 4, puoi utilizzare xCode IDE per lo sviluppo di applicazioni iOS / OS x.

Per cominciare, riteniamo che tu abbia già un account sul sito Web per sviluppatori Apple. Dopo aver effettuato l'accesso, vai al seguente collegamento - Download per sviluppatori Apple

Questo elencherà una serie di software disponibili come segue:

Ora seleziona xCode e scaricalo facendo clic sul collegamento fornito vicino all'immagine del disco. Dopo aver scaricato il file dmg, è possibile installarlo semplicemente facendo doppio clic su di esso e seguendo le istruzioni fornite. Infine, segui le istruzioni fornite e rilascia l'icona xCode nella cartella dell'applicazione.

Ora hai xCode installato sulla tua macchina. Successivamente, apri Xcode dalla cartella dell'applicazione e procedi dopo aver accettato i termini e le condizioni. Se tutto va bene, otterrai la seguente schermata:

Selezionare Get started with a playgroundopzione e inserisci un nome per playground e seleziona iOS come piattaforma. Infine, otterrai la finestra Playground come segue:

Di seguito è riportato il codice preso dalla finestra predefinita di Swift 4 Playground.

import UIKit
var str = "Hello, playground"

Se crei lo stesso programma per il programma OS X, includerà l'importazione di Cocoa e il programma avrà il seguente aspetto:

import Cocoa
var str = "Hello, playground"

Quando il programma di cui sopra viene caricato, dovrebbe visualizzare il seguente risultato nell'area dei risultati di Playground (lato destro).

Hello, playground

Congratulazioni, hai il tuo ambiente di programmazione Swift 4 pronto e puoi procedere con il tuo veicolo di apprendimento "Punto tutorial".

Abbiamo già visto una parte del programma Swift 4 durante la configurazione dell'ambiente. Cominciamo ancora una volta con quanto segueHello, World! programma creato per il playground OS X, che include import Cocoa come mostrato di seguito -

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

print(myString)

Se crei lo stesso programma per il playground iOS, includerà import UIKit e il programma apparirà come segue:

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

Quando eseguiamo il programma precedente utilizzando un playground appropriato, otterremo il seguente risultato:

Hello, World!

Vediamo ora la struttura di base di un programma Swift 4, in modo che sia facile capire gli elementi costitutivi di base del linguaggio di programmazione Swift 4.

Importa in Swift 4

Puoi usare il file importistruzione per importare qualsiasi framework Objective-C (o libreria C) direttamente nel programma Swift 4. Ad esempio, quanto sopraimport cocoa dichiarazione rende disponibili in Swift 4 tutte le librerie, le API e i runtime Cocoa che formano il livello di sviluppo per tutto OS X.

Cocoa è implementato in Objective-C, che è un superset di C, quindi è facile combinare C e persino C ++ nelle tue applicazioni Swift 4.

Gettoni in Swift 4

Un programma Swift 4 è costituito da vari token e un token può essere una parola chiave, un identificatore, una costante, una stringa letterale o un simbolo. Ad esempio, la seguente istruzione Swift 4 è composta da tre token:

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

Commenti

I commenti sono come testi di aiuto nel tuo programma Swift 4. Vengono ignorati dal compilatore. I commenti su più righe iniziano con / * e terminano con i caratteri * / come mostrato di seguito -

/* My first program in Swift 4 */

I commenti su più righe possono essere annidati in Swift 4. Di seguito è riportato un commento valido in Swift 4 -

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

I commenti su una sola riga vengono scritti utilizzando // all'inizio del commento.

// My first program in Swift 4

Punto e virgola

Swift 4 non richiede di digitare un punto e virgola (;) dopo ogni istruzione nel codice, sebbene sia facoltativo; e se usi un punto e virgola, il compilatore non se ne lamenta.

Tuttavia, se si utilizzano più istruzioni nella stessa riga, è necessario utilizzare un punto e virgola come delimitatore, altrimenti il ​​compilatore solleverà un errore di sintassi. Puoi scrivere quanto sopra Hello, World! programmare come segue -

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

Identificatori

Un identificatore Swift 4 è un nome utilizzato per identificare una variabile, una funzione o qualsiasi altro elemento definito dall'utente. Un identificatore inizia con un alfabeto dalla A alla Z o dalla aaz o un trattino basso _ seguito da zero o più lettere, trattini bassi e cifre (da 0 a 9).

Swift 4 non consente caratteri speciali come @, $ e% all'interno degli identificatori. Swift 4 è uncase sensitivelinguaggio di programmazione. Pertanto, Manpower e manpower sono due identificatori diversi in Swift 4. Ecco alcuni esempi di identificatori accettabili:

Azad        zara   abc   move_name   a_123
myname50    _temp  j     a23b9       retVal

Per utilizzare una parola riservata come identificatore, sarà necessario inserire un backtick (`) prima e dopo di essa. Per esempio,class non è un identificatore valido, ma `class`è valido.

Parole chiave

Le seguenti parole chiave sono riservate in Swift 4. Queste parole riservate non possono essere utilizzate come costanti o variabili o altri nomi di identificatori, a meno che non siano preceduti da caratteri di escape:

Parole chiave utilizzate nelle dichiarazioni

Classe deinit Enum estensione
Func importare Dentro interno
Permettere operatore privato protocollo
pubblico statico struct pedice
typealias var

Parole chiave utilizzate nelle dichiarazioni

rompere Astuccio Continua predefinito
fare altro sfumare per
Se in ritorno interruttore
dove mentre

Parole chiave utilizzate in espressioni e tipi

come dynamicType falso è
zero se stesso Se stesso super
vero _COLONNA_ _FILE_ _FUNZIONE_
_LINEA_

Parole chiave utilizzate in contesti particolari

associatività convenienza dinamico didSet
finale ottenere infisso dentro fuori
pigro sinistra mutante nessuna
non mutevole opzionale oltrepassare postfisso
precedenza prefisso Protocollo necessario
destra impostato genere senza proprietario
debole sarà impostato

Spazi bianchi

Una riga contenente solo spazi bianchi, possibilmente con un commento, è nota come riga vuota e un compilatore Swift 4 la ignora completamente.

Lo spazio bianco è il termine utilizzato in Swift 4 per descrivere spazi vuoti, tabulazioni, caratteri di nuova riga e commenti. Gli spazi bianchi separano una parte di un'istruzione da un'altra e consentono al compilatore di identificare dove un elemento in un'istruzione, come int, finisce e inizia l'elemento successivo. Pertanto, nella seguente dichiarazione:

var age

Deve essere presente almeno un carattere di spazio (solitamente uno spazio) tra var e ageaffinché il compilatore sia in grado di distinguerli. D'altra parte, nella seguente dichiarazione:

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

Non sono necessari caratteri di spazio bianco tra frutta e = o tra = e mele, sebbene tu sia libero di includerne alcuni per una migliore leggibilità.

Lo spazio su entrambi i lati di un operatore dovrebbe essere uguale, ad es.

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

Letterali

Un letterale è la rappresentazione del codice sorgente di un valore di un intero, un numero a virgola mobile o un tipo di stringa. I seguenti sono esempi di letterali:

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

Stampa in Swift

Per stampare qualsiasi cosa velocemente abbiamo la parola chiave "print".

La stampa ha tre diverse proprietà.

Items - Articoli da stampare

Separator - separatore tra gli articoli

Terminator - il valore con cui deve finire la riga, vediamo un esempio e la sintassi dello stesso.

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"

Nel codice precedente la prima istruzione print aggiunge \ n, newline Feed come terminatore di default, dove come nella seconda istruzione print abbiamo dato "End" come terminatore, quindi stamperà "End" invece di \ n.

Possiamo fornire il nostro separatore personalizzato e terminatori in base alle nostre esigenze.

Durante la programmazione in qualsiasi linguaggio di programmazione, è necessario utilizzare diversi tipi di variabili per memorizzare le informazioni. Le variabili non sono altro che posizioni di memoria riservate per memorizzare i valori. Ciò significa che quando crei una variabile, riservi dello spazio in memoria.

Potresti voler memorizzare informazioni di vari tipi di dati come stringa, carattere, carattere largo, intero, virgola mobile, booleano, ecc. In base al tipo di dati di una variabile, il sistema operativo alloca memoria e decide cosa può essere memorizzato nel riservato memoria.

Tipi di dati incorporati

Swift 4 offre al programmatore un ricco assortimento di tipi di dati integrati e definiti dall'utente. I seguenti tipi di tipi di dati di base sono più frequentemente quando si dichiarano le variabili:

  • Int or UInt- Viene utilizzato per i numeri interi. Più specificamente, puoi usare Int32, Int64 per definire interi con segno a 32 o 64 bit, mentre UInt32 o UInt64 per definire variabili intere senza segno a 32 o 64 bit. Ad esempio, 42 e -23.

  • Float- Viene utilizzato per rappresentare un numero a virgola mobile a 32 bit e numeri con punti decimali più piccoli. Ad esempio, 3.14159, 0.1 e -273.158.

  • Double- Viene utilizzato per rappresentare un numero a virgola mobile a 64 bit e utilizzato quando i valori a virgola mobile devono essere molto grandi. Ad esempio, 3.14159, 0.1 e -273.158.

  • Bool - Questo rappresenta un valore booleano che è vero o falso.

  • String- Questa è una raccolta ordinata di personaggi. Ad esempio, "Hello, World!"

  • Character- Si tratta di una stringa di un carattere letterale. Ad esempio, "C"

  • Optional - Questo rappresenta una variabile che può contenere un valore o nessun valore.

  • Tuples - Viene utilizzato per raggruppare più valori in un singolo valore composto.

Abbiamo elencato qui alcuni punti importanti relativi ai tipi Integer:

  • In una piattaforma a 32 bit, Int ha le stesse dimensioni di Int32.

  • In una piattaforma a 64 bit, Int ha le stesse dimensioni di Int64.

  • Su una piattaforma a 32 bit, UInt ha le stesse dimensioni di UInt32.

  • Su una piattaforma a 64 bit, UInt ha le stesse dimensioni di UInt64.

  • Int8, Int16, Int32, Int64 possono essere usati per rappresentare forme di numero intero con segno a 8 bit, 16 bit, 32 bit e 64 bit.

  • UInt8, UInt16, UInt32 e UInt64 possono essere utilizzati per rappresentare forme di numero intero senza segno a 8 bit, 16 bit, 32 bit e 64 bit.

Valori vincolati

La tabella seguente mostra il tipo di variabile, la quantità di memoria necessaria per memorizzare il valore in memoria e qual è il valore massimo e minimo che può essere memorizzato in tale tipo di variabili.

genere Larghezza bit tipica Gamma tipica
Int8 1 byte Da -127 a 127
UInt8 1 byte Da 0 a 255
Int32 4 byte -2147483648 a 2147483647
UInt32 4 byte 0 a 4294967295
Int64 8 byte -9223372036854775808 a 9223372036854775807
UInt64 8 byte 0 a 18446744073709551615
Galleggiante 4 byte Da 1.2E-38 a 3.4E + 38 (~ 6 cifre)
Doppio 8 byte Da 2.3E-308 a 1.7E + 308 (~ 15 cifre)

Digitare Alias

È possibile creare un nuovo nome per un tipo esistente utilizzando typealias. Ecco la semplice sintassi per definire un nuovo tipo usando typealias -

typealias newname = type

Ad esempio, la riga seguente indica al compilatore che Feet è un altro nome per Int -

typealias Feet = Int

Ora, la seguente dichiarazione è perfettamente legale e crea una variabile intera chiamata distanza -

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

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato.

100

Tipo di sicurezza

Swift 4 è un linguaggio indipendente dai tipi, il che significa che se una parte del codice si aspetta una stringa, non puoi passarle un Int per errore.

Poiché Swift 4 è indipendente dai tipi, esegue i controlli del tipo durante la compilazione del codice e contrassegna come errori eventuali tipi non corrispondenti.

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

Quando compiliamo il programma precedente, produce il seguente errore in fase di compilazione.

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

Digitare inferenza

L'inferenza del tipo consente a un compilatore di dedurre automaticamente il tipo di una particolare espressione quando compila il codice, semplicemente esaminando i valori forniti. Swift 4 utilizza l'inferenza del tipo per elaborare il tipo appropriato come segue.

// 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)

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

42
3.14159
3.14159

Una variabile ci fornisce una memoria con nome che i nostri programmi possono manipolare. Ogni variabile in Swift 4 ha un tipo specifico, che determina la dimensione e il layout della memoria della variabile; l'intervallo di valori che possono essere memorizzati all'interno di quella memoria; e l'insieme di operazioni che possono essere applicate alla variabile.

Swift 4 supporta i seguenti tipi di variabili di base:

  • Int or UInt- Viene utilizzato per i numeri interi. Più specificamente, puoi usare Int32, Int64 per definire interi con segno a 32 o 64 bit, mentre UInt32 o UInt64 per definire variabili intere senza segno a 32 o 64 bit. Ad esempio, 42 e -23.

  • Float- Viene utilizzato per rappresentare un numero a virgola mobile a 32 bit. Viene utilizzato per contenere numeri con punti decimali più piccoli. Ad esempio, 3.14159, 0.1 e -273.158.

  • Double- Viene utilizzato per rappresentare un numero a virgola mobile a 64 bit e utilizzato quando i valori a virgola mobile devono essere molto grandi. Ad esempio 3.14159, 0.1 e -273.158.

  • Bool - Questo rappresenta un valore booleano che è vero o falso.

  • String- Questa è una raccolta ordinata di personaggi. Ad esempio, "Hello, World!"

  • Character- Si tratta di una stringa di un carattere letterale. Ad esempio, "C"

Swift 4 permette anche di definire vari altri tipi di variabili, che tratteremo nei capitoli successivi, come Optional, Array, Dictionaries, Structures, e Classes.

La sezione seguente spiegherà come dichiarare e utilizzare vari tipi di variabili nella programmazione di Swift 4.

Dichiarazione di variabili

Una dichiarazione di variabile dice al compilatore dove e quanto creare la memoria per la variabile. Prima di utilizzare le variabili, è necessario dichiararle utilizzandovar parola chiave come segue -

var variableName = <initial value>

L'esempio seguente mostra come dichiarare una variabile in Swift 4:

var varA = 42
print(varA)

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

42

Digita Annotazioni

Puoi fornire un file type annotationquando si dichiara una variabile, per essere chiari sul tipo di valori che la variabile può memorizzare. Ecco la sintassi:

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

L'esempio seguente mostra come dichiarare una variabile in Swift 4 utilizzando Annotation. Qui è importante notare che se non stiamo usando l'annotazione del tipo, diventa obbligatorio fornire un valore iniziale per la variabile, altrimenti possiamo semplicemente dichiarare la nostra variabile usando l'annotazione del tipo.

var varA = 42
print(varA)

var varB:Float

varB = 3.14159
print(varB)

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

42
3.1415901184082

Denominazione delle variabili

Il nome di una variabile può essere composto da lettere, cifre e il carattere di sottolineatura. Deve iniziare con una lettera o un trattino basso. Le lettere maiuscole e minuscole sono distinte perché Swift 4 è un linguaggio di programmazione con distinzione tra maiuscole e minuscole.

È possibile utilizzare caratteri semplici o Unicode per denominare le variabili. I seguenti esempi mostrano come assegnare un nome alle variabili:

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

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

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato.

Hello, Swift 4!
你好世界

Variabili di stampa

È possibile stampare il valore corrente di una costante o variabile con la funzione di stampa. È possibile interpolare un valore variabile racchiudendo il nome tra parentesi ed eseguirne l'escape con una barra rovesciata prima della parentesi di apertura: Di seguito sono riportati esempi validi:

var varA = "Godzilla"
var varB = 1000.00

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

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato.

Value of Godzilla is more than 1000.0 millions

Swift 4 introduce anche Optionalstipo, che gestisce l'assenza di un valore. Gli optionals dicono o "c'è un valore ed è uguale a x" o "non c'è affatto un valore".

Un optional è un tipo a sé stante, in realtà una delle nuove enumerazioni super potenti di Swift 4. Ha due possibili valori,None e Some(T), dove T è un valore associato del tipo di dati corretto disponibile in Swift 4.

Ecco una dichiarazione Integer facoltativa:

var perhapsInt: Int?

Ecco una dichiarazione String opzionale:

var perhapsStr: String?

La dichiarazione precedente equivale a inizializzarla esplicitamente a nil che significa nessun valore -

var perhapsStr: String? = nil

Facciamo il seguente esempio per capire come funzionano gli optional in Swift 4:

var myString:String? = nil

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

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

myString has nil value

Gli optional sono simili all'utilizzo nil con i puntatori in Objective-C, ma funzionano per qualsiasi tipo, non solo per le classi.

Scartamento forzato

Se hai definito una variabile come optional, quindi per ottenere il valore da questa variabile, dovrai unwrapesso. Questo significa semplicemente mettere un punto esclamativo alla fine della variabile.

Facciamo un semplice esempio:

var myString:String?

myString = "Hello, Swift 4!"

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

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

Optional("Hello, Swift 4!")

Ora applichiamo lo scartamento per ottenere il valore corretto della variabile -

var myString:String?

myString = "Hello, Swift 4!"

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

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato.

Hello, Swift 4!

Disimballaggio automatico

È possibile dichiarare variabili facoltative utilizzando un punto esclamativo invece di un punto interrogativo. Tali variabili facoltative verranno scartate automaticamente e non è necessario utilizzare ulteriori punti esclamativi alla fine della variabile per ottenere il valore assegnato. Facciamo un semplice esempio:

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

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

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

Hello, Swift 4!

Rilegatura opzionale

Utilizzare l'associazione facoltativa per scoprire se un facoltativo contiene un valore e, in tal caso, per rendere tale valore disponibile come costante o variabile temporanea.

Un'associazione facoltativa per if l'affermazione è la seguente:

if let constantName = someOptional {
   statements
}

Facciamo un semplice esempio per comprendere l'uso dell'associazione facoltativa:

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")
}

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

Your string has - Hello, Swift 4!

Swift 4 introduce anche Tuples tipo, che vengono utilizzati per raggruppare più valori in un unico valore composto.

I valori in una tupla possono essere di qualsiasi tipo e non è necessario che siano dello stesso tipo.

Ad esempio, ("Tutorials Point", 123) è una tupla con due valori, uno di tipo stringa e l'altro è di tipo intero. È un comando legale.

let ImplementationError = (501, "Non implementato") è un errore quando qualcosa sul server non è implementato, restituisce due valori. Codice di errore e descrizione.

Puoi creare tuple da tutti i valori che desideri e da qualsiasi numero di diversi tipi di dati.

Ecco la sintassi della dichiarazione di Tuple:

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

Ecco una dichiarazione di tupla:

var error501 = (501, “Not implemented”)

È possibile accedere ai valori della tupla utilizzando i numeri di indice che iniziano da 0.

Ecco un esempio di accesso ai valori di tupla:

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

Puoi nominare le variabili di una tupla durante la dichiarazione e puoi chiamarle usando i loro nomi

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

Le tuple sono utili per restituire più valori da una funzione. Ad esempio, un'applicazione web potrebbe restituire una tupla di tipo ("String", Int) per mostrare se il caricamento è riuscito o meno.

Restituendo valori diversi in una tupla possiamo prendere decisioni a seconda dei diversi tipi di tupla.

Note - Le tuple sono utili per i valori temporanei e non sono adatte per i dati complessi.

Le costanti si riferiscono a valori fissi che un programma non può alterare durante la sua esecuzione. Le costanti possono essere di uno qualsiasi dei tipi di dati di base come una costante intera, una costante mobile, una costante di carattere o una stringa letterale . Ci sono anche costanti di enumerazione .

Constants vengono trattate come variabili normali tranne per il fatto che i loro valori non possono essere modificati dopo la loro definizione.

Dichiarazione delle costanti

Prima di utilizzare le costanti, è necessario dichiararle utilizzando let parola chiave come segue -

let constantName = <initial value>

Di seguito è riportato un semplice esempio per mostrare come dichiarare una costante in Swift 4:

let constA = 42
print(constA)

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

42

Digita Annotazioni

Puoi fornire un file type annotationquando si dichiara una costante, per essere chiari sul tipo di valori che la costante può memorizzare. La seguente è la sintassi:

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

L'esempio seguente mostra come dichiarare una costante in Swift 4 utilizzando Annotation. Qui è importante notare che è obbligatorio fornire un valore iniziale durante la creazione di una costante:

let constA = 42
print(constA)

let constB:Float = 3.14159
print(constB)

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato.

42
3.1415901184082

Costanti di denominazione

Il nome di una costante può essere composto da lettere, cifre e il carattere di sottolineatura. Deve iniziare con una lettera o un trattino basso. Le lettere maiuscole e minuscole sono distinte perché Swift 4 è un linguaggio di programmazione con distinzione tra maiuscole e minuscole.

È possibile utilizzare caratteri semplici o Unicode per denominare le variabili. Di seguito sono riportati esempi validi:

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

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

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

Hello, Swift 4!
你好世界

Costanti di stampa

È possibile stampare il valore corrente di una costante o variabile utilizzando printfunzione. È possibile interpolare un valore variabile racchiudendo il nome tra parentesi ed eseguirne l'escape con una barra rovesciata prima della parentesi di apertura: Di seguito sono riportati esempi validi:

let constA = "Godzilla"
let constB = 1000.00

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

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

Value of Godzilla is more than 1000.0 millions

Un letterale è la rappresentazione del codice sorgente di un valore di un intero, un numero a virgola mobile o un tipo di stringa. I seguenti sono esempi di letterali:

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

Letterali interi

Un valore letterale intero può essere una costante decimale, binaria, ottale o esadecimale. I letterali binari iniziano con 0b, i letterali ottali iniziano con 0o e i letterali esadecimali iniziano con 0x e nulla per i decimali.

Ecco alcuni esempi di valori letterali interi:

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

Valori letterali a virgola mobile

Un valore letterale a virgola mobile ha una parte intera, una virgola decimale, una parte frazionaria e una parte esponente. È possibile rappresentare i valori letterali in virgola mobile in forma decimale o esadecimale.

I valori letterali a virgola mobile decimali sono costituiti da una sequenza di cifre decimali seguite da una frazione decimale, da un esponente decimale o da entrambi.

I valori letterali a virgola mobile esadecimali sono costituiti da un prefisso 0x, seguito da una frazione esadecimale facoltativa, seguita da un esponente esadecimale.

Ecco alcuni esempi di valori letterali in virgola mobile:

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

Valori letterali stringa

Una stringa letterale è una sequenza di caratteri racchiusi tra virgolette doppie, con la seguente forma:

"characters"

I valori letterali stringa non possono contenere virgolette doppie senza caratteri di escape ("), una barra rovesciata senza caratteri di escape (\), un ritorno a capo o un avanzamento riga. I caratteri speciali possono essere inclusi nei valori letterali stringa utilizzando le seguenti sequenze di escape:

Sequenza di escape Senso
\ 0 Carattere nullo
\\ \personaggio
\ b Backspace
\ f Avanzamento modulo
\ n Nuova linea
\ r Ritorno in carrozza
\ t Tab orizzontale
\ v Scheda verticale
\ ' Citazione singola
\ " Doppia citazione
\ 000 Numero ottale da uno a tre cifre
\ xhh ... Numero esadecimale di una o più cifre

L'esempio seguente mostra come utilizzare alcuni valori letterali di stringa:

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

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

Hello World

Hello'Swift 4'

Valori letterali booleani

Ci sono tre letterali booleani e fanno parte delle parole chiave standard di Swift 4:

  • Un valore di true che rappresenta vero.

  • Un valore di false che rappresenta falso.

  • Un valore di nil non rappresenta alcun valore.

Un operatore è un simbolo che dice al compilatore di eseguire specifiche manipolazioni matematiche o logiche. Objective-C è ricco di operatori incorporati e fornisce i seguenti tipi di operatori:

  • Operatori aritmetici
  • Operatori di confronto
  • Operatori logici
  • Operatori bit per bit
  • Operatori di assegnazione
  • Operatori di intervallo
  • Operatori vari

Questo tutorial spiegherà uno per uno gli operatori aritmetici, relazionali, logici, bit per bit, di assegnazione e altri.

Operatori aritmetici

La tabella seguente mostra tutti gli operatori aritmetici supportati dal linguaggio Swift 4. Assumi variabileA detiene 10 e variabile B detiene 20, quindi -

Operatore Descrizione Esempio
+ Aggiunge due operandi A + B darà 30
- Sottrae il secondo operando dal primo A - B darà -10
* Moltiplica entrambi gli operandi A * B darà 200
/ Divide il numeratore per denominatore B / A darà 2
% Operatore modulo e resto di dopo una divisione intero / float B% A darà 0

Operatori di confronto

La tabella seguente mostra tutti gli operatori relazionali supportati dal linguaggio Swift 4. Assumi variabileA detiene 10 e variabile B detiene 20, quindi -

Operatore Descrizione Esempio
== Controlla se i valori di due operandi sono uguali o meno; se sì, la condizione diventa vera. (A == B) non è vero.
! = Controlla se i valori di due operandi sono uguali o meno; se i valori non sono uguali, la condizione diventa vera. (A! = B) è vero.
> Controlla se il valore dell'operando sinistro è maggiore del valore dell'operando destro; se sì, la condizione diventa vera. (A> B) non è vero.
< Controlla se il valore dell'operando sinistro è inferiore al valore dell'operando destro; se sì, la condizione diventa vera. (A <B) è vero.
> = Controlla se il valore dell'operando sinistro è maggiore o uguale al valore dell'operando destro; se sì, la condizione diventa vera. (A> = B) non è vero.
<= Controlla se il valore dell'operando sinistro è minore o uguale al valore dell'operando destro; se sì, la condizione diventa vera. (A <= B) è vero.

Operatori logici

La tabella seguente mostra tutti gli operatori logici supportati dal linguaggio Swift 4. Assumi variabileA detiene 1 e variabile B contiene 0, quindi -

Operatore Descrizione Esempio
&& Chiamato operatore AND logico. Se entrambi gli operandi sono diversi da zero, la condizione diventa vera. (A && B) è falso.
|| Chiamato Operatore OR logico. Se uno dei due operandi è diverso da zero, la condizione diventa vera. (A || B) è vero.
! Chiamato operatore NOT logico. Utilizzare per invertire lo stato logico del suo operando. Se una condizione è vera, l'operatore NOT logico la renderà falsa. ! (A && B) è vero.

Operatori bit per bit

Gli operatori bit per bit lavorano sui bit ed eseguono operazioni bit per bit. Le tabelle di verità per &, | e ^ sono le seguenti:

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

Gli operatori bit per bit supportati dal linguaggio Swift 4 sono elencati nella tabella seguente. Assumi variabileA detiene 60 e variabile B detiene 13, quindi 7−

Operatore Descrizione Esempio
& L'operatore AND binario copia un po 'nel risultato, se esiste in entrambi gli operandi. (A e B) darà 12, che è 0000 1100
| L'operatore OR binario copia un bit, se esiste in uno degli operandi. (A | B) darà 61, che è 0011 1101
^ L'operatore XOR binario copia il bit, se è impostato in un operando ma non in entrambi. (A ^ B) darà 49, che è 0011 0001
~ Binary Ones Complement Operator è unario e ha l'effetto di "ribaltare" i bit. (~ A) darà -61, che è 1100 0011 in forma di complemento a 2.
<< Operatore binario di spostamento sinistro. Il valore degli operandi di sinistra viene spostato a sinistra del numero di bit specificato dall'operando di destra. (A << 2 darà 240, che è 1111 0000
>> Operatore binario di spostamento a destra. Il valore dell'operando di sinistra viene spostato a destra del numero di bit specificato dall'operando di destra. Un >> 2 darà 15, che è 0000 1111

Operatori di assegnazione

SSwift 4 supporta i seguenti operatori di assegnazione:

Operatore Descrizione Esempio
= Operatore di assegnazione semplice, Assegna i valori dagli operandi del lato destro all'operando del lato sinistro C = A + B assegnerà il valore di A + B a C
+ = Aggiungi operatore di assegnazione AND, aggiunge l'operando destro all'operando sinistro e assegna il risultato all'operando sinistro C + = A è equivalente a C = C + A
- = Sottrai AND operatore di assegnazione, sottrae l'operando destro dall'operando sinistro e assegna il risultato all'operando sinistro C - = A è equivalente a C = C - A
* = Moltiplica AND operatore di assegnazione, moltiplica l'operando destro con l'operando sinistro e assegna il risultato all'operando sinistro C * = A è equivalente a C = C * A
/ = Divide AND operatore di assegnazione, divide l'operando sinistro con l'operando destro e assegna il risultato all'operando sinistro C / = A è equivalente a C = C / A
% = Modulo AND operatore di assegnazione, richiede il modulo utilizzando due operandi e assegna il risultato all'operando sinistro C% = A è equivalente a C = C% A
<< = Shift sinistro AND operatore di assegnazione C << = 2 è uguale a C = C << 2
>> = Spostamento a destra e operatore di assegnazione C >> = 2 è uguale a C = C >> 2
& = Operatore di assegnazione AND bit per bit C & = 2 è uguale a C = C & 2
^ = OR bit per bit esclusivo e operatore di assegnazione C ^ = 2 è uguale a C = C ^ 2
| = OR bit per bit inclusivo e operatore di assegnazione C | = 2 è uguale a C = C | 2

Operatori di intervallo

Swift 4 include due operatori di intervallo, che sono scorciatoie per esprimere un intervallo di valori. La tabella seguente spiega questi due operatori.

Operatore Descrizione Esempio
Gamma chiusa (a ... b) definisce un intervallo che va da a a b, e include i valori a e b. 1 ... 5 dà 1, 2, 3, 4 e 5
Gamma semiaperta (a .. <b) definisce un intervallo che va da a a b, ma non include b. 1 .. <5 restituisce 1, 2, 3 e 4
Gamma unilaterale

a…, definisce un intervallo che va dalla a alla fine degli elementi

... a, definisce un intervallo che inizia dall'inizio ad a

1 ... dà 1, 2,3 ... fine degli elementi

... 2 dà inizio ... a 1,2

Operatori vari

Swift 4 supporta alcuni altri importanti operatori tra cui rangee ? : che sono spiegati nella tabella seguente.

Operatore Descrizione Esempio
Unario meno Il segno di un valore numerico può essere attivato / disattivato utilizzando un prefisso - -3 o -4
Unario Plus Restituisce il valore su cui opera, senza alcuna modifica. +6 dà 6
Condizionale ternario Condizione ? X: Y Se la condizione è vera? Quindi valore X: altrimenti valore Y

Precedenza degli operatori

La precedenza degli operatori determina il raggruppamento dei termini in un'espressione. Ciò influisce sul modo in cui viene valutata un'espressione. Alcuni operatori hanno la precedenza maggiore di altri; ad esempio, l'operatore di moltiplicazione ha una precedenza maggiore dell'operatore di addizione.

Ad esempio, x = 7 + 3 * 2; qui, x è assegnato 13, non 20 perché l'operatore * ha una precedenza maggiore di +, quindi viene prima moltiplicato per 3 * 2 e poi somma in 7.

Qui, gli operatori con la precedenza più alta vengono visualizzati nella parte superiore della tabella, quelli con la priorità più bassa in fondo. All'interno di un'espressione, verranno valutati per primi gli operatori con precedenza più alta.

Operatore Descrizione Esempio
Operatori di espressione primaria () []. espr ++ espr-- da sinistra a destra
Operatori unari

* E + -! ~ ++ expr --expr

* /%

+ -

>> <<

<> <=> =

==! =

da destra a sinistra
Operatori binari

&

^

|

&&

||

da sinistra a destra
Operatore ternario ?: da destra a sinistra
Operatori di assegnazione = + = - = * = / =% = >> = << = & = ^ = | = da destra a sinistra
Virgola , da sinistra a destra

Le strutture decisionali richiedono che il programmatore specifichi una o più condizioni che devono essere valutate o testate dal programma, insieme a una o più istruzioni da eseguire se la condizione è determinata truee, facoltativamente, altre istruzioni da eseguire se si determina che la condizione è false.

Di seguito è riportato il generale di una tipica struttura decisionale presente nella maggior parte dei linguaggi di programmazione:

Swift 4 fornisce i seguenti tipi di dichiarazioni per il processo decisionale. Fare clic sui seguenti collegamenti per verificarne i dettagli.

Suor n Dichiarazione e descrizione
1 istruzione if

Un'istruzione if è costituita da un'espressione booleana seguita da una o più istruzioni.

2 if ... else dichiarazione

Un'istruzione if può essere seguita da un'istruzione else opzionale, che viene eseguita quando l'espressione booleana è falsa.

3 if ... else if ... else Istruzione

Un'istruzione if può essere seguita da un'istruzione else if ... else opzionale, che è molto utile per testare varie condizioni utilizzando l'istruzione if ... else if.

4 istruzioni if ​​annidate

È possibile utilizzare un'istruzione if o else if all'interno di un'altra istruzione if o else if.

5 istruzione switch

Un'istruzione switch consente di verificare l'uguaglianza di una variabile rispetto a un elenco di valori.

Il ? : Operatore

Abbiamo coperto conditional operator ? : nel capitolo precedente che può essere utilizzato per sostituire if...elsedichiarazioni. Ha la seguente forma generale:

Exp1 ? Exp2 : Exp3;

Dove Exp1, Exp2 e Exp3 sono espressioni. Notare l'uso e il posizionamento dei due punti.

Il valore di un? l'espressione è determinata in questo modo: viene valutata Exp1. Se è vero, allora Exp2 viene valutato e diventa il valore dell'intero? espressione. Se Exp1 è falso, viene valutato Exp3 e il suo valore diventa il valore dell'espressione.

Potrebbe esserci una situazione in cui è necessario eseguire un blocco di codice più volte. In generale, le istruzioni vengono eseguite in sequenza: la prima istruzione in una funzione viene eseguita per prima, seguita dalla seconda e così via.

I linguaggi di programmazione forniscono varie strutture di controllo che consentono percorsi di esecuzione più complicati.

Un'istruzione loop ci consente di eseguire un'istruzione o un gruppo di istruzioni più volte. Di seguito è riportato il generale da di un'istruzione loop nella maggior parte dei linguaggi di programmazione:

Il linguaggio di programmazione Swift 4 fornisce i seguenti tipi di loop per gestire i requisiti di loop. Fare clic sui seguenti collegamenti per verificarne i dettagli.

Suor n Tipo e descrizione del loop
1 for-in

Questo ciclo esegue una serie di istruzioni per ogni elemento in un intervallo, sequenza, raccolta o progressione.

2 while loop

Ripete un'istruzione o un gruppo di istruzioni finché una determinata condizione è vera. Verifica la condizione prima di eseguire il corpo del ciclo.

3 ripetere ... durante il ciclo

Come un'istruzione while, tranne per il fatto che verifica la condizione alla fine del corpo del ciclo.

Dichiarazioni di controllo del loop

Le istruzioni di controllo del ciclo cambiano l'esecuzione dalla sua sequenza normale. Quando l'esecuzione esce da un ambito, tutti gli oggetti automatici creati in tale ambito vengono eliminati.

Swift 4 supporta le seguenti istruzioni di controllo. Fare clic sui seguenti collegamenti per verificarne i dettagli.

Suor n Dichiarazione di controllo e descrizione
1 continua dichiarazione

Questa istruzione dice a un ciclo di interrompere ciò che sta facendo e ricominciare dall'inizio della successiva iterazione attraverso il ciclo.

2 dichiarazione di interruzione

Termina l'istruzione loop e trasferisce l'esecuzione all'istruzione immediatamente successiva al loop.

3 dichiarazione fallimentare

L'istruzione fallthrough simula il comportamento dello switch Swift 4 su uno switch in stile C.

Le stringhe in Swift 4 sono una raccolta ordinata di caratteri, come "Hello, World!" e sono rappresentati dal tipo di dati Swift 4String, che a sua volta rappresenta una raccolta di valori di Character genere.

Crea una stringa

È possibile creare una stringa utilizzando un valore letterale stringa o creando un'istanza di una classe String come segue:

// 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)

Quando il codice precedente viene compilato ed eseguito, produce il risultato seguente

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

Stringa vuota

È possibile creare una stringa vuota utilizzando una stringa letterale vuota o creando un'istanza della classe String come mostrato di seguito. È inoltre possibile verificare se una stringa è vuota o meno utilizzando la proprietà booleanaisEmpty.

// 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" )
}

Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato:

stringA is empty
stringB is empty

Costanti di stringa

Puoi specificare se la tua stringa può essere modificata (o mutata) assegnandola a una variabile, oppure sarà costante assegnandola a una costante utilizzando let parola chiave come mostrato di seguito -

// 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 )

Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato:

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

Interpolazione di stringhe

L'interpolazione di stringhe è un modo per costruire un nuovo valore String da una combinazione di costanti, variabili, letterali ed espressioni includendo i loro valori all'interno di una stringa letterale.

Ogni elemento (variabile o costante) che inserisci nella stringa letterale è racchiuso tra una coppia di parentesi, preceduto da una barra rovesciata. Ecco un semplice esempio:

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

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

Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato:

20 times 100 is equal to 2000.0

Concatenazione di stringhe

È possibile utilizzare l'operatore + per concatenare due stringhe o una stringa e un carattere o due caratteri. Ecco un semplice esempio:

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

var stringA = constA + constB
print( stringA )

Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato:

Hello,World!

Lunghezza della stringa

Le corde Swift 4 non hanno l'estensione lengthproprietà, ma puoi usare la funzione globale count () per contare il numero di caratteri in una stringa. Ecco un semplice esempio:

var varA = "Hello, Swift 4!"

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

Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato:

Hello, Swift 4!, length is 15

Confronto tra stringhe

È possibile utilizzare l'operatore == per confrontare due variabili o costanti di stringhe. Ecco un semplice esempio:

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" )
}

Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato:

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

Iterazione delle stringhe

Le stringhe sono di nuovo una raccolta di valori in swift 4, quindi possiamo iterare su stringhe usando i loop. -

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

Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato:

T h i s S t r i n g

Stringhe Unicode

È possibile accedere a una rappresentazione UTF-8 e UTF-16 di una stringa iterando sulle sue proprietà utf8 e utf16 come dimostrato nell'esempio seguente:

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) ")
}

Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato:

UTF-8 Codes: 
68 
111 
103 
63 
63 
63 


UTF-16 Codes: 
68 
111 
103 
63 
63 
63

Funzioni e operatori di stringa

Swift 4 supporta un'ampia gamma di metodi e operatori relativi alle stringhe:

Suor n Funzioni / operatori e scopo
1

isEmpty

Un valore booleano che determina se una stringa è vuota o meno.

2

hasPrefix(prefix: String)

Funzione per verificare se una determinata stringa di parametri esiste o meno come prefisso della stringa.

3

hasSuffix(suffix: String)

Funzione per verificare se una determinata stringa di parametri esiste o meno come suffisso della stringa.

4

toInt()

Funzione per convertire il valore String numerico in Integer.

5

count()

Funzione globale per contare il numero di caratteri in una stringa.

6

utf8

Proprietà per restituire una rappresentazione UTF-8 di una stringa.

7

utf16

Proprietà per restituire una rappresentazione UTF-16 di una stringa.

8

unicodeScalars

Proprietà per restituire una rappresentazione scalare Unicode di una stringa.

9

+

Operatore per concatenare due stringhe, o una stringa e un carattere, o due caratteri.

10

+=

Operatore per aggiungere una stringa o un carattere a una stringa esistente.

11

==

Operatore per determinare l'uguaglianza di due stringhe.

12

<

Operatore per eseguire un confronto lessicografico per determinare se una stringa viene valutata come minore di un'altra.

13

startIndex

Per ottenere il valore all'inizio dell'indice di stringa.

14

endIndex

Per ottenere il valore all'indice finale della stringa.

15

Indices

Per accedere agli indici uno per uno. cioè tutti i caratteri della stringa uno per uno.

16

insert("Value", at: position)

Per inserire un valore in una posizione.

17

remove(at: position)

removeSubrange(range)

per rimuovere un valore in una posizione o per rimuovere un intervallo di valori dalla stringa.

18

reversed()

restituisce il contrario di una stringa

UN character in Swift è un singolo carattere String letterale, indirizzato dal tipo di dati Character. Dai un'occhiata al seguente esempio. Utilizza due costanti carattere:

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

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

Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato:

Value of char1 A
Value of char2 B

Se provi a memorizzare più di un carattere in una variabile o costante di tipo Carattere, Swift 4 non lo consentirà. Prova a digitare il seguente esempio in Swift 4 Playground e riceverai un errore anche prima della compilazione.

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

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

Variabili di carattere vuote

Non è possibile creare una variabile o una costante Character vuota che avrà un valore vuoto. La seguente sintassi non è possibile:

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

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

Accesso ai caratteri da stringhe

Come spiegato parlando delle stringhe di Swift 4, String rappresenta una raccolta di valori di carattere in un ordine specificato. Quindi possiamo accedere ai singoli caratteri dalla stringa data iterando su quella stringa con unfor-in loop -

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

Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato:

H
e
l
l
o

Concatenazione di stringhe con caratteri

L'esempio seguente mostra come il personaggio di Swift 4 può essere concatenato con la stringa di Swift 4.

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

varA.append( varB )

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

Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato:

Value of varC = Hello G

Gli array di Swift 4 vengono utilizzati per memorizzare elenchi ordinati di valori dello stesso tipo. Swift 4 esegue un controllo rigoroso che non ti consente di inserire un tipo sbagliato in un array, anche per errore.

Se si assegna un array creato a una variabile, è sempre modificabile, il che significa che è possibile modificarlo aggiungendo, rimuovendo o cambiando i suoi elementi; ma se si assegna un array a una costante, allora quell'array è immutabile e la sua dimensione e il suo contenuto non possono essere modificati.

Creazione di array

È possibile creare un array vuoto di un certo tipo utilizzando la seguente sintassi dell'inizializzatore:

var someArray = [SomeType]()

Ecco la sintassi per creare un array di una data dimensione a * e inizializzarlo con un valore -

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

È possibile utilizzare la seguente istruzione per creare un array vuoto di Int tipo con 3 elementi e il valore iniziale come zero -

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

Di seguito è riportato un altro esempio per creare un array di tre elementi e assegnare tre valori a tale array:

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

Accesso agli array

È possibile recuperare un valore da un array utilizzando subscript sintassi, passando l'indice del valore che si desidera recuperare tra parentesi quadre immediatamente dopo il nome dell'array come segue:

var someVar = someArray[index]

Qui, il indexparte da 0, il che significa che è possibile accedere al primo elemento utilizzando l'indice come 0, il secondo elemento è accessibile utilizzando l'indice come 1 e così via. L'esempio seguente mostra come creare, inizializzare e accedere agli array:

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])" )

Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato:

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

Modifica degli array

Puoi usare append()metodo o operatore di assegnazione di addizione (+ =) per aggiungere un nuovo elemento alla fine di un array. Dai un'occhiata al seguente esempio. Qui, inizialmente, creiamo un array vuoto e quindi aggiungiamo nuovi elementi nello stesso array -

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])" )

Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato:

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

È possibile modificare un elemento esistente di un array assegnando un nuovo valore a un determinato indice come mostrato nell'esempio seguente:

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])" )

Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato:

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

Iterazione su un array

Puoi usare for-in loop per iterare sull'intero set di valori in un array come mostrato nell'esempio seguente:

var someStrs = [String]()

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

Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato:

Apple
Amazon
Google

Puoi usare enumerate() funzione che restituisce l'indice di un elemento insieme al suo valore come mostrato di seguito nell'esempio seguente:

var someStrs = [String]()

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

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

Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato:

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

Aggiunta di due array

È possibile utilizzare l'operatore di addizione (+) per aggiungere due array dello stesso tipo che produrrà un nuovo array con una combinazione di valori dei due array come segue:

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

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

Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato:

2
2
1
1
1

La proprietà del conteggio

Puoi usare il file di sola lettura count proprietà di un array per scoprire il numero di elementi in un array mostrato di seguito -

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)")

Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato:

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

La proprietà vuota

Puoi usare il file di sola lettura empty proprietà di un array per scoprire se un array è vuoto o meno come mostrato di seguito -

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)")

Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato:

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

Swift 4 sets sono usati per memorizzare valori distinti dello stesso tipo ma non hanno un ordine definito come gli array.

È possibile utilizzare set invece di array se l'ordinamento degli elementi non è un problema o se si desidera assicurarsi che non vi siano valori duplicati. (gli insiemi consentono solo valori distinti.)

Un tipo deve essere modificabile per essere memorizzato in un set. Un valore hash è un valore Int uguale per oggetti uguali. Ad esempio, se x == y, allorax.hashvalue == y.hashvalue.

Tutti i valori swift di base sono di tipo hashable per impostazione predefinita e possono essere utilizzati come valori impostati.

Creazione di set

È possibile creare un set vuoto di un certo tipo utilizzando la seguente sintassi dell'inizializzatore:

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

Accesso e modifica dei set

È possibile accedere o modificare un set utilizzando i suoi metodi e proprietà -

Il metodo "count" può essere utilizzato per mostrare il numero di elementi nel set.

someSet.count        // prints the number of elements

Il metodo "insert" può essere utilizzato per inserire valori nel set.

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

Allo stesso modo, isEmpty può essere utilizzato per verificare se set è vuoto.

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

Il metodo "remove" può essere utilizzato per rimuovere il valore nel set.

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

Il metodo "contiene" può essere utilizzato per verificare l'esistenza del valore in un insieme.

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

Iterazione su un Set

Puoi iterare su un set usando il ciclo for-in -

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)
}

Esecuzione di operazioni sugli insiemi

È possibile eseguire operazioni di base sui set su Swift Set.

Di seguito sono riportati i metodi per eseguire le operazioni di impostazione:

  • 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 dictionariesvengono utilizzati per memorizzare elenchi non ordinati di valori dello stesso tipo. Swift 4 mette un controllo rigoroso che non ti consente di inserire un tipo sbagliato in un dizionario anche per sbaglio.

I dizionari di Swift 4 utilizzano un identificatore univoco noto come file keyper memorizzare un valore che in seguito può essere referenziato e cercato tramite la stessa chiave. A differenza degli elementi in un array, gli elementi in un filedictionarynon hai un ordine specificato. Puoi usare un filedictionary quando è necessario cercare valori in base ai loro identificatori.

Una chiave del dizionario può essere un numero intero o una stringa senza limitazioni, ma dovrebbe essere univoca all'interno di un dizionario.

Se assegni un dizionario creato a una variabile, è sempre modificabile, il che significa che puoi modificarlo aggiungendo, rimuovendo o cambiando i suoi elementi. Ma se assegni un dizionario a una costante, quel dizionario è immutabile e la sua dimensione e il suo contenuto non possono essere modificati.

Creazione del dizionario

Puoi creare un dizionario vuoto di un certo tipo usando la seguente sintassi dell'inizializzatore:

var someDict = [KeyType: ValueType]()

È possibile utilizzare la seguente semplice sintassi per creare un dizionario vuoto la cui chiave sarà di tipo Int ei valori associati saranno stringhe:

var someDict = [Int: String]()

Ecco un esempio per creare un dizionario da un insieme di valori dati:

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

Inizializzazione basata su sequenza

Swift 4 ti consente di creare un dizionario da array (coppie chiave-valore).

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

È possibile utilizzare la seguente semplice sintassi per creare un dizionario vuoto la cui chiave sarà di tipo Int ei valori associati saranno stringhe:

var Distance = [2000,10, 620]

Ecco un esempio per creare un dizionario da un insieme di valori dati:

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

Le righe di codice sopra creeranno un dizionario con Città come chiave e Distanza come Valore -

Filtraggio

Swift 4 ti consente di filtrare i valori da un dizionario.

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

Se eseguiamo il codice sopra, il nostro dizionario closeCities sarà.

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

Dizionario raggruppamento

Swift 4 ti consente di creare raggruppamenti di valori del dizionario.

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

È possibile utilizzare la seguente semplice sintassi per raggruppare i valori del dizionario in base al primo alfabeto.

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

Il risultato del codice precedente sarà

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

Accesso ai dizionari

È possibile recuperare un valore da un dizionario utilizzando la sintassi del pedice, passando la chiave del valore che si desidera recuperare tra parentesi quadre immediatamente dopo il nome del dizionario come segue:

var someVar = someDict[key]

Controlliamo il seguente esempio per creare, inizializzare e accedere ai valori da un dizionario:

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])" )

Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato:

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

Modifica dei dizionari

Puoi usare updateValue(forKey:)metodo per aggiungere un valore esistente a una determinata chiave del dizionario. Questo metodo restituisce un valore facoltativo del tipo di valore del dizionario. Ecco un semplice esempio:

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])" )

Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato:

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")

È possibile modificare un elemento esistente di un dizionario assegnando un nuovo valore a una determinata chiave come mostrato nell'esempio seguente:

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])" )

Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato:

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")

Rimuovi coppie chiave-valore

Puoi usare removeValueForKey()metodo per rimuovere una coppia chiave-valore da un dizionario. Questo metodo rimuove la coppia chiave-valore se esiste e restituisce il valore rimosso oppure restituisce zero se non esiste alcun valore. Ecco un semplice esempio:

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])" )

Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato:

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

È inoltre possibile utilizzare la sintassi pedice per rimuovere una coppia chiave-valore da un dizionario assegnando un valore di nilper quella chiave. Ecco un semplice esempio:

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])" )

Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato:

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

Iterazione su un dizionario

Puoi usare un file for-in loop per iterare sull'intero set di coppie chiave-valore in un dizionario come mostrato nell'esempio seguente:

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

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

Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato:

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

Puoi usare enumerate() funzione che restituisce l'indice dell'elemento insieme alla sua coppia (chiave, valore) come mostrato di seguito nell'esempio -

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

Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato:

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")

Converti in array

Puoi estrarre un elenco di coppie chiave-valore da un dato dizionario per creare array separati sia per le chiavi che per i valori. Ecco un esempio:

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)")
}

Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato:

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

La proprietà del conteggio

Puoi usare il file di sola lettura count proprietà di un dizionario per scoprire il numero di elementi in un dizionario come mostrato di seguito -

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)")

Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato:

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

La proprietà vuota

Puoi usare la sola lettura empty proprietà di un dizionario per scoprire se un dizionario è vuoto o meno, come mostrato di seguito -

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)")

Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato:

someDict1 = false
someDict2 = false
someDict3 = true

Una funzione è un insieme di istruzioni organizzate insieme per eseguire un'attività specifica. Una funzione di Swift 4 può essere semplice come una semplice funzione C o complessa come una funzione del linguaggio Objective C. Ci consente di passare i valori dei parametri locali e globali all'interno delle chiamate di funzione.

  • Function Declaration - indica al compilatore il nome di una funzione, il tipo restituito e i parametri.

  • Function Definition - Fornisce il corpo effettivo della funzione.

Le funzioni di Swift 4 contengono il tipo di parametro ei relativi tipi di ritorno.

Definizione di funzione

In Swift 4, una funzione è definita dalla parola chiave "func". Quando una funzione viene definita di recente, può assumere uno o più valori come "parametri" di input per la funzione ed elaborerà le funzioni nel corpo principale e restituirà i valori alle funzioni come output "tipi di ritorno".

Ogni funzione ha un nome di funzione, che descrive l'attività che la funzione esegue. Per utilizzare una funzione, devi "chiamare" quella funzione con il suo nome e passare i valori di input (noti come argomenti) che corrispondono ai tipi dei parametri della funzione. I parametri delle funzioni vengono anche chiamati "tuple".

Gli argomenti di una funzione devono essere sempre forniti nello stesso ordine dell'elenco dei parametri della funzione ei valori restituiti sono seguiti da →.

Sintassi

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

Dai un'occhiata al seguente codice. Il nome dello studente viene dichiarato come tipo di dati stringa dichiarato all'interno della funzione "studente" e quando la funzione viene chiamata, restituirà il nome dello studente.

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

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

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

First Program
About Functions

Chiamare una funzione

Supponiamo di aver definito una funzione chiamata "display" per considerare ad esempio di visualizzare i numeri una funzione con nome di funzione "display" viene inizializzata prima con l'argomento "no1" che contiene il tipo di dati intero. Quindi l'argomento "no1" viene assegnato all'argomento "a", che d'ora in poi punterà allo stesso tipo di dati intero. Ora l'argomento "a" viene restituito alla funzione. Qui la funzione display () manterrà il valore intero e restituirà i valori interi ogni volta che la funzione viene invocata.

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

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

Quando eseguiamo il programma sopra usando playground, otteniamo il seguente risultato:

100
200

Parametri e valori restituiti

Swift 4 fornisce parametri di funzione flessibili e i suoi valori di ritorno da valori semplici a valori complessi. Simile a quella di C e Objective C, le funzioni in Swift 4 possono anche assumere diverse forme.

Funzioni con parametri

Si accede a una funzione passando i valori dei suoi parametri al corpo della funzione. Possiamo passare da uno a più valori di parametro come tuple all'interno della funzione.

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))

Quando eseguiamo il programma sopra usando playground, otteniamo il seguente risultato:

40
45
120

Funzioni senza parametri

Potremmo anche avere funzioni senza parametri.

Sintassi

func funcname() -> datatype {
   return datatype
}

Di seguito è riportato un esempio con una funzione senza un parametro:

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

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

Alice

Funzioni con valori di ritorno

Le funzioni vengono utilizzate anche per restituire valori di tipo di dati stringa, intero e float come tipi restituiti. Per trovare il numero più grande e più piccolo in un dato array, la funzione 'ls' è dichiarata con tipi di dati interi grandi e piccoli.

Un array viene inizializzato per contenere valori interi. Quindi l'array viene elaborato e ogni valore nell'array viene letto e confrontato per il valore precedente. Quando il valore è minore del precedente viene memorizzato nell'argomento 'small', altrimenti viene memorizzato nell'argomento 'large' ei valori vengono restituiti chiamando la funzione.

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)")

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

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

Funzioni senza valori di ritorno

Alcune funzioni possono avere argomenti dichiarati all'interno della funzione senza alcun valore di ritorno. Il seguente programma dichiaraa e bcome argomenti della funzione sum (). all'interno della funzione stessa i valori per gli argomentia e b vengono passati invocando la funzione chiamata sum () ei suoi valori vengono stampati eliminando così i valori di ritorno.

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)

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

30 20
50 40
30 24

Funzioni con tipi restituiti opzionali

Swift 4 introduce la funzione "opzionale" per eliminare i problemi introducendo una misura di sicurezza. Considera, ad esempio, che stiamo dichiarando il tipo di ritorno dei valori della funzione come intero, ma cosa accadrà quando la funzione restituisce un valore stringa o un valore nullo. In tal caso il compilatore restituirà un valore di errore. vengono introdotti "opzionali" per eliminare questi problemi.

Le funzioni opzionali assumeranno due forme "valore" e "zero". Citeremo "Optionals" con il carattere riservato chiave "?" per verificare se la tupla restituisce un valore o un valore nullo.

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)")
}

Quando eseguiamo il programma sopra utilizzando playground, otteniamo il seguente risultato:

min is -6 and max is 109

'' Optionals 'sono usati per controllare i valori' nil 'o garbage, consumando così molto tempo nel debugging e rendendo il codice efficiente e leggibile per l'utente.

Funzioni locali vs nomi di parametri esterni

Nomi dei parametri locali

I nomi dei parametri locali sono accessibili solo all'interno della funzione.

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

Qui, il funcIl numero di argomento sample è dichiarato come variabile interna poiché vi si accede internamente dalla funzione sample (). Qui il 'numero' è dichiarato come variabile locale ma il riferimento alla variabile è fatto al di fuori della funzione con la seguente dichiarazione -

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

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

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

1
2
3

Nomi dei parametri esterni

I nomi dei parametri esterni ci consentono di nominare i parametri di una funzione per rendere più chiaro il loro scopo. Ad esempio di seguito è possibile nominare due parametri di funzione e quindi chiamare quella funzione come segue:

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)

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

125

Parametri variadici

Quando vogliamo definire una funzione con un numero multiplo di argomenti, possiamo dichiarare i membri come parametri "variadici". I parametri possono essere specificati come variadici da (···) dopo il nome del parametro.

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")

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

4
3
5
4.5
3.1
5.6
Swift 4
Enumerations
Closures

Parametri costanti, variabili e I / O

Le funzioni di default considerano i parametri come 'costanti', mentre l'utente può dichiarare gli argomenti delle funzioni anche come variabili. Abbiamo già discusso del fatto che la parola chiave "let" viene utilizzata per dichiarare parametri costanti e che i parametri variabili vengono definiti con la parola chiave "var".

I parametri I / O in Swift 4 forniscono funzionalità per mantenere i valori dei parametri anche se i valori vengono modificati dopo la chiamata alla funzione. All'inizio della definizione del parametro della funzione, la parola chiave 'inout' viene dichiarata per mantenere i valori del membro.

Deriva la parola chiave "inout" poiché i suoi valori vengono passati "in" alla funzione e i suoi valori sono accessibili e modificati dal suo corpo della funzione e viene restituito "out" dalla funzione per modificare l'argomento originale.

Le variabili vengono passate solo come argomento per il parametro in-out poiché i suoi valori vengono modificati solo all'interno e all'esterno della funzione. Quindi non è necessario dichiarare stringhe e valori letterali come parametri in-out. '&' prima del nome di una variabile fa riferimento al fatto che stiamo passando l'argomento al parametro in-out.

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)")

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

Swapped values are 10, 2

Tipi di funzione e suo utilizzo

Ogni funzione segue la funzione specifica considerando i parametri di input e restituisce il risultato desiderato.

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

Di seguito è riportato un esempio:

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

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

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

2
6

Qui la funzione viene inizializzata con due argomenti no1 e no2 come tipi di dati interi e anche il suo tipo restituito viene dichiarato 'int'

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

Qui la funzione è dichiarata come string tipo di dati.

Le funzioni possono anche avere void i tipi di dati e tali funzioni non restituiranno nulla.

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

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

Swift 4 Functions
Types and its Usage

La funzione precedente è dichiarata come una funzione void senza argomenti e senza valori di ritorno.

Utilizzo dei tipi di funzione

Le funzioni vengono prima passate con argomenti di tipo intero, float o stringa e quindi vengono passate come costanti o variabili alla funzione come indicato di seguito.

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

Qui sum è un nome di funzione con variabili intere 'a' e 'b' che ora è dichiarata come variabile per l'aggiunta del nome della funzione. Di seguito, sia la funzione di addizione che quella di somma hanno entrambe lo stesso numero di argomenti dichiarati come tipo di dati intero e restituiscono anche valori interi come riferimenti.

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

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

Result: 129

Tipi di funzione come tipi di parametro e tipi restituiti

Possiamo anche passare la funzione stessa come tipi di parametro a un'altra funzione.

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)

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

Result: 129
Result: 30

Funzioni annidate

Una funzione annidata fornisce la possibilità di chiamare la funzione esterna invocando la funzione interna.

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())

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

-30

Le chiusure in Swift 4 sono simili a quelle delle funzioni autonome organizzate come blocchi e chiamate ovunque come i linguaggi C e Objective C. Costanti e riferimenti variabili definiti all'interno delle funzioni vengono catturati e memorizzati nelle chiusure. Le funzioni sono considerate casi speciali di chiusure e assume le tre forme seguenti:

Funzioni globali Funzioni annidate Espressioni di chiusura
Avere un nome. Non acquisire alcun valore Avere un nome. Cattura i valori dalla funzione che racchiude Le chiusure senza nome acquisiscono i valori dai blocchi adiacenti

Le espressioni di chiusura nel linguaggio Swift 4 seguono stili di sintassi nitidi, ottimizzati e leggeri che includono.

  • Deduzione di tipi di parametri e valori restituiti dal contesto.
  • Ritorni impliciti da chiusure a espressione singola.
  • Nomi di argomenti abbreviati e
  • Sintassi di chiusura finale

Sintassi

Di seguito è riportata una sintassi generica per definire la chiusura che accetta parametri e restituisce un tipo di dati -

{
   (parameters) −> return type in
   statements
}

Di seguito è riportato un semplice esempio:

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

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

Welcome to Swift Closures

La chiusura seguente accetta due parametri e restituisce un valore Bool -

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

Di seguito è riportato un semplice esempio:

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

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

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

10

Espressioni nelle chiusure

Le funzioni annidate forniscono un modo conveniente per denominare e definire blocchi di codice. Invece di rappresentare l'intera dichiarazione di funzione e i costrutti del nome vengono utilizzati per denotare funzioni più brevi. La rappresentazione della funzione in una breve dichiarazione chiara con sintassi focalizzata si ottiene tramite espressioni di chiusura.

Programma di ordine crescente

L'ordinamento di una stringa è ottenuto dalla funzione riservata "ordinato" del tasto Swift 4s, che è già disponibile nella libreria standard. La funzione ordinerà le stringhe date in ordine crescente e restituirà gli elementi in un nuovo array con la stessa dimensione e tipo di dati menzionati nel vecchio array. Il vecchio array rimane lo stesso.

Due argomenti sono rappresentati all'interno della funzione ordinata:

  • Valori di tipo noto rappresentati come array.

  • Il contenuto dell'array (Int, Int) e restituisce un valore booleano (Bool) se l'array è ordinato correttamente restituirà un valore true, altrimenti restituirà false.

Una normale funzione con una stringa di input viene scritta e passata alla funzione ordinata per ottenere le stringhe ordinate nel nuovo array che viene mostrato di seguito -

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

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

Quando eseguiamo il programma sopra utilizzando playground, otteniamo il seguente risultato:

true

L'array iniziale da ordinare per il gelato è "Swift 4" e "great". La funzione per ordinare l'array è dichiarata come tipo di dati stringa e il suo tipo restituito è indicato come Boolean. Entrambe le stringhe vengono confrontate e ordinate in ordine crescente e memorizzate in un nuovo array. Se l'ordinamento viene eseguito correttamente, la funzione restituirà un valore true, altrimenti restituirà false.

Usi della sintassi delle espressioni di chiusura:

  • parametri costanti,
  • parametri variabili e
  • parametri inout.

L'espressione di chiusura non supportava i valori predefiniti. I parametri variabili e le tuple possono essere utilizzati anche come tipi di parametro e tipi restituiti.

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

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

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

30

I parametri e le dichiarazioni del tipo restituito menzionati nell'istruzione della funzione possono anche essere rappresentati dalla funzione di espressione di chiusura inline con la parola chiave 'in'. Una volta dichiarati parametri e restituiti, la parola chiave "in" viene utilizzata per indicare il corpo della chiusura.

Restituzioni implicite a espressione singola

Qui, il tipo di funzione del secondo argomento della funzione ordinata rende chiaro che un valore Bool deve essere restituito dalla chiusura. Poiché il corpo della chiusura contiene una singola espressione (s1> s2) che restituisce un valore Bool, non vi è ambiguità e la parola chiave return può essere omessa.

Per restituire un'istruzione di espressione singola nelle chiusure dell'espressione, la parola chiave 'return' viene omessa nella sua parte di dichiarazione.

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)

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

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

L'istruzione stessa definisce chiaramente che quando stringa1 è maggiore di stringa 2 restituisce true altrimenti false, quindi l'istruzione return viene omessa qui.

Chiusure di tipo noto

Considera l'aggiunta di due numeri. Sappiamo che l'aggiunta restituirà il tipo di dati intero. Quindi le chiusure di tipo noto sono dichiarate come:

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

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

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

-10

Dichiarare nomi di argomenti stenografici come chiusure

Swift 4 fornisce automaticamente nomi di argomenti abbreviati alle chiusure inline, che possono essere utilizzati per fare riferimento ai valori degli argomenti della chiusura con i nomi $ 0, $1, $2 e così via.

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

Qui, $ 0 e $ 1 si riferiscono al primo e al secondo argomento String della chiusura.

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

200

Swift 4 facilita all'utente di rappresentare le chiusure in linea come nomi di argomenti abbreviati rappresentando $ 0, $1, $2 --- $ n.

L'elenco degli argomenti delle chiusure viene omesso nella sezione delle definizioni quando rappresentiamo i nomi degli argomenti abbreviati all'interno delle espressioni di chiusura. In base al tipo di funzione verranno derivati ​​i nomi abbreviati degli argomenti. Poiché l'argomento abbreviato è definito nel corpo dell'espressione, la parola chiave "in" viene omessa.

Chiusure come funzioni dell'operatore

Swift 4 fornisce un modo semplice per accedere ai membri fornendo semplicemente le funzioni dell'operatore come chiusure. Negli esempi precedenti la parola chiave "Bool" viene utilizzata per restituire "true" quando le stringhe sono uguali, altrimenti restituisce "false".

L'espressione è resa ancora più semplice dalla funzione operatore in chiusura come:

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)

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

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

Chiusure come rimorchi

Il passaggio dell'argomento finale della funzione a un'espressione di chiusura viene dichiarato con l'aiuto di "Chiusure finali". È scritto al di fuori della funzione () con {}. Il suo utilizzo è necessario quando non è possibile scrivere la funzione inline su una singola riga.

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

dove {$ 0> $ 1} sono rappresentati come chiusure finali dichiarate all'esterno di (nomi).

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)

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

[NO, EA, WE, SO]

Acquisizione di valori e tipi di riferimento

In Swift 4, l'acquisizione di costanti e valori delle variabili viene eseguita con l'aiuto delle chiusure. Inoltre fa riferimento e modifica i valori per quelle costanti e variabili all'interno del corpo di chiusura anche se le variabili non esistono più.

L'acquisizione di valori costanti e variabili si ottiene utilizzando la funzione annidata scrivendo funzione con nel corpo di un'altra funzione.

Una funzione annidata acquisisce -

  • Argomenti della funzione esterna.
  • Cattura le costanti e le variabili definite all'interno della funzione Outer.

In Swift 4, quando una costante o una variabile viene dichiarata all'interno di una funzione, anche i riferimenti a tali variabili vengono creati automaticamente dalla chiusura. Fornisce inoltre la possibilità di riferire più di due variabili alla stessa chiusura come segue:

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

Qui oneDecrement e le variabili Decrement punteranno entrambe lo stesso blocco di memoria come riferimento di chiusura.

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()

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

82
64
46

Ogni volta che viene chiamata la funzione esterna calcDecrement, essa richiama la funzione decrementer () e decrementa il valore di 18 e restituisce il risultato con l'aiuto della funzione esterna calcDecrement. Qui calcDecrement funge da chiusura.

Anche se la funzione decrementer () non ha argomenti, la chiusura per impostazione predefinita si riferisce alle variabili 'overallDecrement' e 'total' catturandone i valori esistenti. La copia dei valori per le variabili specificate viene memorizzata con la nuova funzione decrementer (). Swift 4 gestisce le funzioni di gestione della memoria allocando e deallocando gli spazi di memoria quando le variabili non sono in uso.

Un'enumerazione è un tipo di dati definito dall'utente costituito da un insieme di valori correlati. Parola chiaveenum viene utilizzato per definire il tipo di dati enumerato.

Funzionalità di enumerazione

L'enumerazione in Swift 4 ricorda anche la struttura di C e dell'Obiettivo C.

  • È dichiarato in una classe e ai suoi valori si accede tramite l'istanza di quella classe.

  • Il valore del membro iniziale viene definito utilizzando gli intializzatori enum.

  • La sua funzionalità viene inoltre estesa garantendo la funzionalità del protocollo standard.

Sintassi

Le enumerazioni vengono introdotte con la parola chiave enum e collocano la loro intera definizione all'interno di un paio di parentesi graffe -

enum enumname {
   // enumeration values are described here
}

Ad esempio, è possibile definire un'enumerazione per i giorni della settimana come segue:

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

Esempio

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")
}

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

Welcome to Closures

L'enumerazione Swift 4 non assegna ai suoi membri il valore predefinito come C e Objective C. Invece i membri sono definiti esplicitamente dai loro nomi di enumerazione. Il nome dell'enumerazione deve iniziare con una lettera maiuscola (Es: enum DaysofaWeek).

var weekDay = DaysofaWeek.Sunday

Qui il nome dell'enumerazione 'DaysofaWeek' è assegnato a un giorno della settimana variabile. Informa il compilatore che il tipo di dati appartiene a Sunday verrà assegnato ai successivi membri enum di quella particolare classe. Una volta definito il tipo di dati del membro enum, è possibile accedere ai membri passando valori e ulteriori calcoli.

Enumerazione con istruzione Switch

Anche l'istruzione "Switch" di Swift 4 segue la selezione a più vie. Si accede a una sola variabile in un determinato momento in base alla condizione specificata. Il caso predefinito nell'istruzione switch viene utilizzato per intercettare casi non specificati.

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")
   
}

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

Climate is Cold

Il programma definisce innanzitutto Climate come nome dell'enumerazione. Quindi i suoi membri come "India", "America", "Africa" ​​e "Australia" vengono dichiarati appartenenti alla classe "Clima". Ora il membro America è assegnato a una variabile stagionale. Inoltre, Switch case vedrà i valori corrispondenti a .America e si diramerà a quella particolare istruzione. L'output verrà visualizzato come "Climate is Cold". Allo stesso modo è possibile accedere a tutti i membri tramite istruzioni switch. Quando la condizione non è soddisfatta, stampa per impostazione predefinita "Il clima non è prevedibile".

L'enumerazione può essere ulteriormente classificata in valori associati e valori grezzi.

Differenza tra valori associati e valori grezzi

Valori associati Valori grezzi
Tipi di dati diversi Stessi tipi di dati
Es: enum {10,0.8, "Hello"} Es: enum {10,35,50}
I valori vengono creati in base a una costante o una variabile Valori prepopolati
Varia quando dichiarato ogni volta Il valore per il membro è lo stesso

Enum con valori associati

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).")
}

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

Student Marks are: 98,97,95.

Si consideri ad esempio per accedere al nome degli studenti e ai voti assicurati in tre materie il nome dell'enumerazione è dichiarato come studente e i membri presenti nella classe enum sono il nome che appartiene al tipo di dati stringa, i voti sono rappresentati come segno1, segno2 e segno3 del tipo di dati Integer. Per accedere al nome dello studente o ai voti che hanno ottenuto

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

Ora, il caso dello switch stamperà il nome dello studente se quel blocco del caso viene eseguito altrimenti stamperà i voti assicurati dallo studente. Se entrambe le condizioni falliscono, verrà eseguito il blocco predefinito.

Enum con valori grezzi

I valori non elaborati possono essere stringhe, caratteri o qualsiasi tipo di numero intero o in virgola mobile. Ogni valore non elaborato deve essere univoco all'interno della sua dichiarazione di enumerazione. Quando vengono utilizzati numeri interi per i valori non elaborati, vengono incrementati automaticamente se non viene specificato alcun valore per alcuni membri dell'enumerazione.

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).")

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

Value of the Month is: 5.

Swift 4 fornisce una base flessibile per l'utilizzo di costrutti come strutture. Facendo uso di queste strutture una volta è possibile definire i metodi e le proprietà dei costrutti.

A differenza di C e Objective C

  • La struttura non necessita di file di implementazione e interfaccia.

  • La struttura ci permette di creare un unico file e di estendere automaticamente la sua interfaccia ad altri blocchi.

In Struttura i valori delle variabili vengono copiati e passati nei codici successivi restituendo una copia dei vecchi valori in modo che i valori non possano essere modificati.

Sintassi

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

Definizione di una struttura

Si consideri ad esempio, si supponga di dover accedere al record degli studenti contenente i voti di tre materie e di scoprire il totale di tre materie. Qui markStruct viene utilizzato per inizializzare una struttura con tre segni come tipo di dati "Int".

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

Accesso alla struttura e alle sue proprietà

Ai membri della struttura si accede tramite il nome della struttura. Le istanze della struttura vengono inizializzate dalla parola chiave "let".

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)")

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

Mark1 is 100
Mark2 is 200
Mark3 is 300

Si accede ai voti degli studenti con il nome della struttura "studentMarks". I membri della struttura vengono inizializzati come mark1, mark2, mark3 con valori di tipo intero. Quindi la struttura studentMarks () viene passata ai "mark" con la parola chiave "let". Di seguito i "segni" conterranno i valori dei membri della struttura. Ora i valori vengono stampati accedendo ai valori dei membri della struttura con "." con i suoi nomi inizializzati.

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

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

98
97

Migliori pratiche di utilizzo delle strutture

Il linguaggio Swift 4 fornisce la funzionalità per definire strutture come tipi di dati personalizzati per la creazione dei blocchi funzione. Le istanze di struttura vengono passate per il suo valore ai blocchi definiti per ulteriori manipolazioni.

Necessità di avere strutture

  • Per incapsulare valori di dati semplici.

  • Per copiare i dati incapsulati e le proprietà associate per "valori" anziché per "riferimenti".

  • Struttura in "Copia" e "Riferimento".

Le strutture in Swift 4 trasmettono i propri membri con i propri valori anziché in base ai propri riferimenti.

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)

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

98
96
100

Un altro esempio

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)

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

34
42
13

La struttura 'markStruct' viene definita prima con i suoi membri mark1, mark2 e mark3. Ora le variabili delle classi membri vengono inizializzate per contenere valori interi. Quindi la copia dei membri della struttura viene creata con la parola chiave "self". Una volta creata la copia dei membri della struttura, il blocco struttura con i suoi contrassegni dei parametri viene passato alla variabile "segni" che ora conterrà i voti degli studenti. Quindi i segni vengono stampati come 98, 96, 100. Passaggio successivo per gli stessi membri della struttura, un'altra istanza denominata "fail" viene utilizzata per indicare gli stessi membri della struttura con segni diversi. Quindi i risultati vengono ora stampati come 34, 42, 13. Questo spiega chiaramente che le strutture avranno una copia delle variabili membro e quindi passeranno i membri ai blocchi funzione successivi.

Le classi in Swift 4 sono elementi costitutivi di costrutti flessibili. Simile a costanti, variabili e funzioni, l'utente può definire proprietà e metodi di classe. Swift 4 ci fornisce la funzionalità che durante la dichiarazione delle classi gli utenti non devono creare interfacce o file di implementazione. Swift 4 ci consente di creare classi come un singolo file e le interfacce esterne verranno create per impostazione predefinita una volta inizializzate le classi.

Vantaggi di avere lezioni

  • L'ereditarietà acquisisce le proprietà di una classe in un'altra classe

  • Il casting del tipo consente all'utente di controllare il tipo di classe in fase di esecuzione

  • I deinizializzatori si occupano del rilascio delle risorse di memoria

  • Il conteggio dei riferimenti consente all'istanza della classe di avere più di un riferimento

Caratteristiche comuni di classi e strutture

  • Le proprietà sono definite per memorizzare i valori
  • I pedici sono definiti per fornire l'accesso ai valori
  • I metodi vengono inizializzati per migliorare la funzionalità
  • Lo stato iniziale è definito dagli inizializzatori
  • Le funzionalità vengono espanse oltre i valori predefiniti
  • Conferma degli standard di funzionalità del protocollo

Sintassi

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

Definizione di classe

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

La sintassi per la creazione di istanze

let studrecord = student()

Esempio

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

class studentMarks {
   var mark = 300
}

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

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

Mark is 300

Accesso alle proprietà delle classi come tipi di riferimento

È possibile accedere alle proprietà della classe con "." sintassi. Il nome della proprietà è separato da un "." dopo il nome dell'istanza.

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)")

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

Mark1 is 300
Mark2 is 400
Mark3 is 900

Operatori di identità di classe

Le classi in Swift 4 fanno riferimento a più costanti e variabili che puntano a una singola istanza. Per conoscere le costanti e le variabili che puntano a una particolare istanza di classe vengono utilizzati operatori di identità. Le istanze di classe vengono sempre passate per riferimento. Nelle classi le istanze NSString, NSArray e NSDictionary vengono sempre assegnate e passate come riferimento a un'istanza esistente, anziché come copia.

Identico agli operatori Non identico agli operatori
L'operatore utilizzato è (===) L'operatore utilizzato è (! ==)
Restituisce vero quando due costanti o variabili puntano a una stessa istanza Restituisce vero quando due costanti o variabili puntano a un'istanza diversa
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)")

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

main.SampleClass
main.SampleClass

Il linguaggio Swift 4 fornisce proprietà per classe, enumerazione o struttura per associare valori. Le proprietà possono essere ulteriormente classificate in Proprietà memorizzate e Proprietà calcolate.

Differenza tra proprietà memorizzate e proprietà calcolate

Proprietà immagazzinata Proprietà calcolata
Memorizza valori costanti e variabili come istanza Calcola un valore anziché memorizzarlo
Fornito da classi e strutture Fornito da classi, enumerazioni e strutture

Entrambe le proprietà Stored e Computed sono associate al tipo di istanza. Quando le proprietà sono associate ai valori del tipo, viene definito come "Proprietà del tipo". Le proprietà memorizzate e calcolate sono generalmente associate a istanze di un tipo particolare. Tuttavia, le proprietà possono anche essere associate al tipo stesso. Tali proprietà sono note come proprietà del tipo. Vengono utilizzati anche osservatori di proprietà

  • Per osservare il valore delle proprietà memorizzate
  • Per osservare la proprietà della sottoclasse ereditata derivata dalla superclasse

Proprietà memorizzate

Swift 4 introduce il concetto di proprietà memorizzata per memorizzare le istanze di costanti e variabili. Le proprietà memorizzate delle costanti sono definite dalla parola chiave "let" e le proprietà memorizzate delle variabili sono definite dalla parola chiave "var".

  • Durante la definizione, la proprietà memorizzata fornisce il "valore predefinito"
  • Durante l'inizializzazione l'utente può inizializzare e modificare i valori iniziali
struct Number {
   var digits: Int
   let pi = 3.1415
}

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

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

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

67
3.1415

Considera la seguente riga nel codice sopra:

let pi = 3.1415

Qui, la variabile pi viene inizializzata come valore di proprietà memorizzato con l'istanza pi = 3.1415. Quindi, ogni volta che l'istanza viene riferita, manterrà solo il valore 3,1415.

Un altro metodo per avere proprietà memorizzate è avere come strutture costanti. Quindi l'intera istanza delle strutture verrà considerata come "Proprietà memorizzate delle costanti".

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

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

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

Invece di reinizializzare il "numero" a 8.7, restituirà un messaggio di errore che indica che il "numero" è dichiarato come costante.

Proprietà immagazzinata pigra

Swift 4 fornisce una proprietà flessibile chiamata "Proprietà memorizzata pigra" in cui non calcolerà i valori iniziali quando la variabile viene inizializzata per la prima volta. Il modificatore "pigro" viene utilizzato prima della dichiarazione della variabile per averla come proprietà memorizzata in modo pigro.

Vengono utilizzate le proprietà pigre:

  • Per ritardare la creazione di oggetti.
  • Quando la proprietà dipende da altre parti di una classe, che non sono ancora note
class sample {
   lazy var no = number()    // `var` declaration is required.
}

class number {
   var name = "Swift 4"
}

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

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

Swift 4

Variabili di istanza

In Objective C, le proprietà archiviate hanno anche variabili di istanza a scopo di backup per memorizzare i valori dichiarati nella proprietà archiviata.

Swift 4 integra entrambi questi concetti in un'unica dichiarazione di "proprietà memorizzata". Invece di avere una variabile di istanza corrispondente e un valore di backup, la "proprietà memorizzata" contiene tutte le informazioni integrate definite in un'unica posizione sulla proprietà delle variabili in base al nome della variabile, al tipo di dati e alle funzionalità di gestione della memoria.

Proprietà calcolate

Piuttosto che memorizzare i valori, le proprietà calcolate forniscono un getter e un setter opzionale per recuperare e impostare altre proprietà e valori indirettamente.

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)

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

(150.0, 75.0)
-150.0
-65.0

Quando una proprietà calcolata lascia il nuovo valore indefinito, il valore predefinito verrà impostato per quella particolare variabile.

Proprietà calcolate come proprietà di sola lettura

Una proprietà di sola lettura nella proprietà calcolata è definita come una proprietà con getter ma senza setter. Viene sempre utilizzato per restituire un valore. Le variabili sono ulteriormente accessibili tramite un '.' Sintassi ma non può essere impostata su un altro valore.

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"]!)

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

Swift 4 Properties
3.09

Proprietà calcolate come osservatori di proprietà

In Swift 4 per osservare e rispondere ai valori delle proprietà vengono utilizzati gli osservatori delle proprietà. Ogni volta che vengono impostati i valori delle proprietà vengono chiamati gli osservatori di proprietà. Ad eccezione delle proprietà memorizzate pigre, possiamo aggiungere osservatori di proprietà alla proprietà "ereditata" mediante il metodo "sovrascrittura".

Gli osservatori di proprietà possono essere definiti da entrambi

  • Prima di memorizzare il valore - willset

  • Dopo aver memorizzato il nuovo valore - didset

  • Quando una proprietà è impostata in un inizializzatore, non è possibile chiamare gli osservatori di set e didset.

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

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

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

Variabili locali e globali

Le variabili locali e globali vengono dichiarate per il calcolo e l'osservazione delle proprietà.

Variabili locali Variabili globali
Variabili definite all'interno di una funzione, un metodo o un contesto di chiusura. Variabili definite al di fuori di funzione, metodo, chiusura o contesto di tipo.
Utilizzato per archiviare e recuperare i valori. Utilizzato per archiviare e recuperare i valori.
Le proprietà memorizzate vengono utilizzate per ottenere e impostare i valori. Le proprietà memorizzate vengono utilizzate per ottenere e impostare i valori.
Vengono utilizzate anche le proprietà calcolate. Vengono utilizzate anche le proprietà calcolate.

Proprietà del tipo

Le proprietà sono definite nella sezione Definizione del tipo con parentesi graffe {} e anche l'ambito delle variabili è definito in precedenza. Per definire le proprietà del tipo per i tipi di valore viene utilizzata la parola chiave "statica" e per i tipi di classe viene utilizzata la parola chiave "classe".

Sintassi

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
   }
}

Interrogazione e impostazione delle proprietà

Proprio come le proprietà dell'istanza, le proprietà del tipo vengono interrogate e impostate con "." Sintassi solo sul tipo invece di puntare all'istanza.

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)

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

97
87

Nel linguaggio Swift 4, le funzioni associate a tipi particolari vengono chiamate metodi. In Objective C le classi vengono utilizzate per definire i metodi, mentre il linguaggio Swift 4 fornisce all'utente la flessibilità di disporre di metodi per classi, strutture ed enumerazioni.

Metodi di istanza

Nel linguaggio Swift 4, le istanze di classi, strutture ed enumerazioni sono accessibili tramite i metodi dell'istanza.

I metodi di istanza forniscono funzionalità

  • Per accedere e modificare le proprietà dell'istanza
  • funzionalità relative alle necessità dell'istanza

Il metodo di istanza può essere scritto all'interno delle parentesi graffe {}. Ha accesso implicito ai metodi e alle proprietà dell'istanza del tipo. Quando viene chiamata un'istanza specifica del tipo, avrà accesso a quella particolare istanza.

Sintassi

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

Esempio

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()

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

Result is: 880
Result is: 850

Calcoli di classe definisce due metodi di istanza:

  • init () è definito per aggiungere due numeri aeb e memorizzarli nel risultato 'res'
  • tot () viene utilizzato per sottrarre il valore "res" dal passaggio del valore "c"

Infine, per stampare i metodi di calcolo con valori per aeb viene chiamato. Si accede ai metodi di istanza con "." sintassi dei punti

Nomi dei parametri locali ed esterni

Le funzioni di Swift 4 descrivono le dichiarazioni locali e globali per le loro variabili. Allo stesso modo, anche le convenzioni di denominazione di Swift 4 Methods assomigliano a quelle dell'obiettivo C. Ma le caratteristiche delle dichiarazioni dei nomi dei parametri locali e globali sono diverse per funzioni e metodi. Il primo parametro in Swift 4 è indicato dai nomi delle preposizioni come "with", "for" e "by" per convenzioni di denominazione di facile accesso.

Swift 4 offre la flessibilità nei metodi dichiarando il nome del primo parametro come nomi di parametri locali e i restanti nomi di parametri come nomi di parametri globali. Qui "no1" viene dichiarato dai metodi Swift 4 come nomi di parametri locali. 'no2' viene utilizzato per le dichiarazioni globali e vi si accede tramite il programma.

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)

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

600
320
3666

Nome parametro esterno con # e simbolo _

Anche se i metodi Swift 4 forniscono i primi nomi dei parametri per le dichiarazioni locali, l'utente ha la possibilità di modificare i nomi dei parametri dalle dichiarazioni locali a quelle globali. Questo può essere fatto anteponendo il simbolo "#" al primo nome del parametro. In questo modo, è possibile accedere al primo parametro globalmente in tutti i moduli.

Quando l'utente deve accedere ai nomi dei parametri successivi con un nome esterno, il nome del metodo viene sovrascritto con l'aiuto del simbolo "_".

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)

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

2400
500
45000

Proprietà personale nei metodi

I metodi hanno una proprietà implicita nota come "self" per tutte le sue istanze di tipo definite. La proprietà 'Self' viene utilizzata per fare riferimento alle istanze correnti per i metodi definiti.

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()

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

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

Modifica dei tipi di valore dai metodi di istanza

In Swift 4 le strutture linguistiche e le enumerazioni appartengono a tipi di valore che non possono essere modificati dai suoi metodi di istanza. Tuttavia, il linguaggio Swift 4 offre la flessibilità di modificare i tipi di valore "mutando" il comportamento. Mutate apporterà tutte le modifiche ai metodi dell'istanza e tornerà alla forma originale dopo l'esecuzione del metodo. Inoltre, dalla proprietà "self" viene creata una nuova istanza per la sua funzione implicita e sostituirà il metodo esistente dopo la sua esecuzione

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)

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

9
15
270
450
81000
135000

Proprietà personale per il metodo mutante

La modifica dei metodi combinati con la proprietà 'self' assegna una nuova istanza al metodo definito.

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)

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato. -

39
65

Metodi di tipo

Quando viene chiamata una particolare istanza di un metodo, viene chiamata come metodo Instance; e quando il metodo chiama un particolare tipo di metodo, viene chiamato "Type Methods". I metodi di tipo per le "classi" sono definiti dalla parola chiave "func" e i metodi di tipo per strutture ed enumerazioni sono definiti con la parola chiave "static" prima della parola chiave "func".

I metodi di tipo vengono chiamati e acceduti da "." sintassi in cui invece di chiamare una particolare istanza viene invocato l'intero metodo.

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)

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato. -

35
5

L'accesso ai membri dell'elemento di una raccolta, sequenza e un elenco in Classi, Strutture ed Enumerazioni viene effettuato con l'aiuto di pedici. Questi pedici vengono utilizzati per memorizzare e recuperare i valori con l'aiuto di index. Gli elementi array sono accessibili con l'aiuto di someArray [index] e gli elementi membri successivi in ​​un'istanza di Dictionary possono essere acceduti come someDicitonary [key].

Per un singolo tipo, gli indici possono variare da dichiarazioni singole a più dichiarazioni. Possiamo usare il pedice appropriato per sovraccaricare il tipo di valore di indice passato al pedice. Gli indici variano anche da dimensione singola a dimensione multipla in base ai requisiti degli utenti per le dichiarazioni del tipo di dati di input.

Sintassi della dichiarazione dei pedici e suo utilizzo

Facciamo un riepilogo delle proprietà calcolate. Anche gli indici seguono la stessa sintassi di quella delle proprietà calcolate. Per l'interrogazione di istanze di tipo, i pedici vengono scritti all'interno di una parentesi quadra seguita dal nome dell'istanza. La sintassi pedice segue la stessa struttura di sintassi di "metodo di istanza" e sintassi di "proprietà calcolata". La parola chiave "pedice" viene utilizzata per definire i pedici e l'utente può specificare uno o più parametri con i rispettivi tipi di ritorno. Gli indici possono avere proprietà di lettura-scrittura o di sola lettura e le istanze vengono memorizzate e recuperate con l'aiuto delle proprietà "getter" e "setter" come quelle delle proprietà calcolate.

Sintassi

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

Esempio 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")

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

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

Esempio 2

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])

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

Sunday
Monday
Tuesday
Wednesday

Opzioni in pedice

Subscripts accetta da uno a più parametri di input e questi parametri di input appartengono anche a qualsiasi tipo di dati. Possono anche utilizzare parametri variabili e variadici. Gli indici non possono fornire valori di parametro predefiniti o utilizzare parametri in-out.

La definizione di più pedici viene definita "sovraccarico di pedici" in cui una classe o una struttura può fornire più definizioni di pedici come richiesto. Questi più pedici vengono dedotti in base ai tipi di valori dichiarati all'interno delle parentesi graffe.

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])")

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

1.0

L'indice di Swift 4 supporta dichiarazioni da un parametro a più parametri per i tipi di dati appropriati. Il programma dichiara la struttura "Matrix" come una matrice di matrice dimensionale 2 * 2 per memorizzare i tipi di dati "Double". Il parametro Matrix viene immesso con i tipi di dati Integer per la dichiarazione di righe e colonne.

La nuova istanza per Matrix viene creata passando il conteggio di righe e colonne all'inizializzazione come mostrato di seguito.

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

I valori della matrice possono essere definiti passando i valori di riga e di colonna nel pedice, separati da una virgola come mostrato di seguito.

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

La capacità di assumere più forme è definita eredità. Generalmente una classe può ereditare metodi, proprietà e funzionalità da un'altra classe. Le classi possono essere ulteriormente classificate in sottoclasse e superclasse.

  • Sub Class - quando una classe eredita proprietà, metodi e funzioni da un'altra classe, viene chiamata come sottoclasse

  • Super Class - La classe contenente proprietà, metodi e funzioni per ereditare altre classi da se stessa viene chiamata come una super classe

Le classi Swift 4 contengono una superclasse che chiama e accede a metodi, proprietà, funzioni e metodi di sostituzione. Inoltre, gli osservatori di proprietà vengono utilizzati anche per aggiungere una proprietà e modificare i metodi di proprietà memorizzati o calcolati.

Classe di base

Una classe che non eredita metodi, proprietà o funzioni da un'altra classe viene chiamata "Classe base".

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)

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

Swift 4
98
89
76

La classe con nome classe StudDetails è qui definita come una classe base che viene utilizzata per contenere il nome degli studenti e tre materie contrassegnate come mark1, mark2 e mark3. La parola chiave 'let' viene utilizzata per inizializzare il valore per la classe base e il valore della classe base viene visualizzato nel playground con l'aiuto della funzione 'print'.

Sottoclasse

L'atto di basare una nuova classe su una classe esistente è definito come "sottoclasse". La sottoclasse eredita le proprietà, i metodi e le funzioni della sua classe base. Per definire una sottoclasse ':' viene utilizzato prima del nome della classe di base

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()

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

Mark1:93, Mark2:89

La classe "StudDetails" è definita come super classe in cui vengono dichiarati i voti degli studenti e la sottoclasse "display" viene utilizzata per ereditare i voti dalla sua super classe. La sottoclasse definisce i voti degli studenti e chiama il metodo print () per visualizzare il voto degli studenti.

Overriding

L'accesso all'istanza della super classe, ai metodi di tipo, all'istanza, alle proprietà del tipo e alla sottoclasse dei pedici fornisce il concetto di sovrascrittura. La parola chiave 'override' viene utilizzata per sovrascrivere i metodi dichiarati nella superclasse.

Accesso a metodi, proprietà e pedici della super classe

La parola chiave 'super' viene utilizzata come prefisso per accedere a metodi, proprietà e pedici dichiarati nella super classe

Overriding Accesso a metodi, proprietà e pedici
Metodi super.somemethod ()
Proprietà super.someProperty ()
Pedici super [someIndex]

Metodi che sovrascrivono

I metodi di istanza e tipo ereditati possono essere sovrascritti dalla parola chiave 'override' sui nostri metodi definiti nella nostra sottoclasse. Qui print () viene sovrascritto nella sottoclasse per accedere alla proprietà type menzionata nella super classe print (). Anche la nuova istanza della super classe cricket () viene creata come "cricinstance".

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()

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

Welcome to Swift Super Class
Welcome to Swift Sub Class

Sostituzione della proprietà

È possibile sovrascrivere un'istanza ereditata o una proprietà di classe per fornire il proprio getter e setter personalizzato per quella proprietà oppure aggiungere osservatori di proprietà per consentire alla proprietà di sovrascrittura di osservare quando il valore della proprietà sottostante cambia.

Sostituzione di proprietà get e setter

Swift 4 consente all'utente di fornire getter e setter personalizzati per sovrascrivere la proprietà ereditata, indipendentemente dal fatto che si tratti di una proprietà memorizzata o calcolata. La sottoclasse non conosce il nome e il tipo di proprietà ereditata. Pertanto è essenziale che l'utente debba specificare nella sottoclasse, il nome e il tipo della proprietà sovrascritta specificata in superclasse.

Questo può essere fatto in due modi:

  • Quando setter è definito per sovrascrivere la proprietà, l'utente deve definire anche getter.

  • Quando non vogliamo modificare la proprietà getter ereditata, possiamo semplicemente passare il valore ereditato dalla sintassi "super.someProperty" alla super classe.

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)")

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

Radius of rectangle for 25.0  is now overridden as 3

Ignorare gli osservatori di proprietà

Quando è necessario aggiungere una nuova proprietà per una proprietà ereditata, in Swift 4 viene introdotto il concetto di "sostituzione della proprietà". Ciò avvisa l'utente quando il valore della proprietà ereditata viene alterato. Ma l'override non è applicabile alle proprietà memorizzate costanti ereditate e alle proprietà calcolate di sola lettura ereditate.

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)")

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

Radius of rectangle for 25.0  is now overridden as 3
Radius of rectangle for 100.0  is now overridden as 21

Proprietà finale per impedire l'override

Quando l'utente non desidera che altri accedano a metodi, proprietà o pedici di una super classe, Swift 4 introduce la proprietà "finale" per impedire l'override. Una volta che la proprietà 'finale' è stata dichiarata, gli indici non permetteranno di sovrascrivere i metodi, le proprietà e i suoi pedici della super classe. Non è previsto che la proprietà "finale" sia in "super classe". Quando viene dichiarata la proprietà "finale", l'utente è limitato a creare ulteriori sottoclassi.

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)")

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

<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

Poiché la super classe è dichiarata come "finale" e anche i suoi tipi di dati sono dichiarati come "finale", il programma non consentirà di creare ulteriori sottoclassi e genererà errori.

Classi, strutture ed enumerazioni una volta dichiarate in Swift 4 vengono inizializzate per preparare l'istanza di una classe. Il valore iniziale viene inizializzato per la proprietà memorizzata e anche per le nuove istanze i valori vengono inizializzati per procedere ulteriormente. La parola chiave per creare la funzione di inizializzazione viene eseguita dal metodo 'init ()'. L'inizializzatore di Swift 4 differisce da Objective-C per il fatto che non restituisce alcun valore. La sua funzione è controllare l'inizializzazione delle istanze appena create prima della sua elaborazione. Swift 4 fornisce anche un processo di "deinizializzazione" per eseguire operazioni di gestione della memoria una volta che le istanze sono state deallocate.

Ruolo inizializzatore per proprietà archiviate

La proprietà memorizzata deve inizializzare le istanze per le sue classi e strutture prima di elaborare le istanze. Le proprietà memorizzate utilizzano l'inizializzatore per assegnare e inizializzare i valori eliminando così la necessità di chiamare osservatori di proprietà. L'inizializzatore viene utilizzato nella proprietà archiviata

  • Per creare un valore iniziale.

  • Per assegnare un valore di proprietà predefinito all'interno della definizione della proprietà.

  • Per inizializzare un'istanza per un particolare tipo di dati viene utilizzato 'init ()'. Nessun argomento viene passato all'interno della funzione init ().

Sintassi

init() {
   //New Instance initialization goes here
}

Esempio

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)")

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

area of rectangle is 72.0

Qui la struttura "rettangolo" viene inizializzata con la lunghezza e la larghezza dei membri come tipi di dati "doppi". Il metodo Init () viene utilizzato per inizializzare i valori per i membri appena creati length e double. L'area del rettangolo viene calcolata e restituita chiamando la funzione rettangolo.

Impostazione dei valori delle proprietà per impostazione predefinita

Il linguaggio Swift 4 fornisce la funzione Init () per inizializzare i valori delle proprietà memorizzate. Inoltre, l'utente ha la possibilità di inizializzare i valori delle proprietà per impostazione predefinita mentre dichiara i membri della classe o della struttura. Quando la proprietà assume lo stesso valore da sola in tutto il programma, possiamo dichiararla solo nella sezione della dichiarazione invece di inizializzarla in init (). L'impostazione dei valori delle proprietà per impostazione predefinita abilita l'utente quando l'ereditarietà è definita per classi o strutture.

struct rectangle {
   var length = 6
   var breadth = 12
}

var area = rectangle()
print("area of rectangle is \(area.length*area.breadth)")

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

area of rectangle is 72

Qui invece di dichiarare lunghezza e larghezza in init () i valori vengono inizializzati nella dichiarazione stessa.

Inizializzazione dei parametri

Nella lingua Swift 4 l'utente ha la possibilità di inizializzare i parametri come parte della definizione dell'inizializzatore utilizzando init ().

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)")

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

area is: 72.0
area is: 432.0

Parametri locali ed esterni

I parametri di inizializzazione hanno nomi di parametri sia locali che globali simili a quelli dei parametri di funzione e metodo. La dichiarazione dei parametri locali viene utilizzata per accedere all'interno del corpo di inizializzazione e la dichiarazione dei parametri esterni viene utilizzata per chiamare l'inizializzatore. Gli inizializzatori di Swift 4 differiscono dall'inizializzatore di funzione e metodo in quanto non identificano quale inizializzatore viene utilizzato per chiamare quali funzioni.

Per ovviare a ciò, Swift 4 introduce un nome esterno automatico per ogni parametro in init (). Questo nome esterno automatico è equivalente al nome locale scritto prima di ogni parametro di inizializzazione.

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)")

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

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

Parametri senza nomi esterni

Quando un nome esterno non è necessario per l'inizializzazione, il trattino basso "_" viene utilizzato per sovrascrivere il comportamento predefinito.

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)")

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

area is: 180.0
area is: 370.0
area is: 110.0

Tipi di proprietà opzionali

Quando la proprietà memorizzata in un'istanza non restituisce alcun valore, tale proprietà viene dichiarata con un tipo "opzionale" che indica che "nessun valore" viene restituito per quel particolare tipo. Quando la proprietà memorizzata viene dichiarata come 'opzionale', inizializza automaticamente il valore in modo che sia 'nullo' durante l'inizializzazione stessa.

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)")

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

area is: Optional(180.0)
area is: Optional(370.0)
area is: Optional(110.0)

Modifica delle proprietà delle costanti durante l'inizializzazione

L'inizializzazione consente inoltre all'utente di modificare anche il valore della proprietà costante. Durante l'inizializzazione, la proprietà della classe consente alle sue istanze di classe di essere modificate dalla super classe e non dalla sottoclasse. Si consideri ad esempio nel programma precedente "length" è dichiarato come "variabile" nella classe principale. La seguente variabile di programma "length" viene modificata come variabile "costante".

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)")

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

area is: Optional(180.0)
area is: Optional(370.0)
area is: Optional(110.0)

Inizializzatori predefiniti

Gli inizializzatori predefiniti forniscono una nuova istanza a tutte le sue proprietà dichiarate di classe o struttura di base con valori predefiniti.

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)")

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato. -

result is: nil
result is: 98
result is: true

Il programma precedente è definito con il nome della classe "defaultexample". Tre funzioni membro vengono inizializzate per impostazione predefinita come "studname?" per memorizzare i valori "nil", "stmark" come 98 e "pass" come valore booleano "true". Allo stesso modo, i valori dei membri nella classe possono essere inizializzati come predefiniti prima di elaborare i tipi di membri della classe.

Inizializzatori di membri per i tipi di struttura

Quando gli inizializzatori personalizzati non vengono forniti dall'utente, i tipi di struttura in Swift 4 riceveranno automaticamente l '"inizializzatore per membri". La sua funzione principale è inizializzare le nuove istanze della struttura con l'inizializzazione predefinita per i membri e quindi le nuove proprietà dell'istanza vengono passate per l'inizializzazione per i membri per nome.

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)")

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

Area of rectangle is: 24.0
Area of rectangle is: 32.0

Le strutture vengono inizializzate per impostazione predefinita per le loro funzioni di appartenenza durante l'inizializzazione per "length" come "100.0" e "breadth" come "200.0". Ma i valori vengono sovrascritti durante l'elaborazione della lunghezza e della larghezza delle variabili come 24.0 e 32.0.

Delega dell'inizializzatore per i tipi di valore

La delega dell'inizializzatore è definita come la chiamata di inizializzatori da altri inizializzatori. La sua funzione principale è quella di agire come riutilizzabilità per evitare la duplicazione del codice su più inizializzatori.

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)")

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

(0.0,0.0) (0.0,0.0)
(2.0,2.0) 5.0,5.0)
(2.5,2.5) (3.0,3.0)

Regole per la delega dell'inizializzatore

Tipi di valore Tipi di classe
L'ereditarietà non è supportata per tipi di valore come strutture ed enumerazioni. Il riferimento ad altri inizializzatori viene effettuato tramite self.init L'ereditarietà è supportata. Verifica che tutti i valori delle proprietà memorizzate siano inizializzati

Ereditarietà e inizializzazione delle classi

I tipi di classe hanno due tipi di inizializzatori per verificare se le proprietà memorizzate definite ricevono un valore iniziale, ovvero inizializzatori designati e inizializzatori di convenienza.

Inizializzatori designati e inizializzatori di convenienza

Inizializzatore designato Convenience Initializer
Considerato come inizializzazioni primarie per una classe Considerato come inizializzazione di supporto per una classe
Tutte le proprietà della classe vengono inizializzate e l'inizializzatore della superclasse appropriato viene chiamato per un'ulteriore inizializzazione L'inizializzatore designato viene chiamato con convenienza inizializzatore per creare un'istanza di classe per un caso d'uso specifico o un tipo di valore di input
Almeno un inizializzatore designato è definito per ogni classe Non è necessario avere inizializzatori di convenienza obbligatori definiti quando la classe non richiede inizializzatori.
Init (parametri) {istruzioni} convenienza init (parametri) {istruzioni}

Programma per inizializzatori designati

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)")

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

res is: 10
res is: 10
res is: 20

Programma per inizializzatori di convenienza

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)")

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

res is: 20
res is: 30
res is: 50

Ereditarietà e sostituzione dell'inizializzatore

Swift 4 non consente alle sue sottoclassi di ereditare i suoi inizializzatori di superclassi per i loro tipi di membri per impostazione predefinita. L'ereditarietà è applicabile agli inizializzatori di classe Super solo in una certa misura che verrà discussa in Ereditarietà dell'inizializzatore automatico.

Quando l'utente deve avere inizializzatori definiti in superclasse, la sottoclasse con inizializzatori deve essere definita dall'utente come implementazione personalizzata. Quando la sottoclasse deve essere sostituita dalla parola chiave "override" della super classe deve essere dichiarata.

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)")

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

Rectangle: 4 sides
Pentagon: 5 sides

Inizializzatori designati e convenienti in azione

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)
   }
}

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

Planet name is: Mercury
No Planets like that: [No Planets]

Inizializzatore non riuscito

L'utente deve essere avvisato quando si verificano errori di inizializzazione durante la definizione di una classe, struttura o valori di enumerazione. L'inizializzazione delle variabili a volte diventa un errore a causa di -

  • Valori dei parametri non validi.
  • Assenza di fonte esterna richiesta.
  • Condizione che impedisce la riuscita dell'inizializzazione.

Per rilevare le eccezioni generate dal metodo di inizializzazione, Swift 4 produce un'inizializzazione flessibile chiamata "inizializzatore non riuscito" per notificare all'utente che qualcosa non viene notato durante l'inizializzazione della struttura, della classe o dei membri dell'enumerazione. La parola chiave per rilevare l'inizializzatore non riuscito è "init?". Inoltre, gli inizializzatori failable e non failable non possono essere definiti con gli stessi tipi di parametri e nomi.

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")
}

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

Student name is specified
Student name is left blank

Inizializzatori non riusciti per le enumerazioni

Il linguaggio Swift 4 offre la flessibilità di avere inizializzatori non riusciti anche per le enumerazioni per notificare all'utente quando i membri dell'enumerazione sono lasciati dall'inizializzazione dei valori.

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")
}

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

With In Block Two
Block Does Not Exist

Inizializzatori non riusciti per le classi

Un inizializzatore non riuscito quando dichiarato con enumerazioni e strutture segnala un errore di inizializzazione in qualsiasi circostanza all'interno della sua implementazione. Tuttavia, l'inizializzatore non riuscito nelle classi avviserà l'errore solo dopo che le proprietà memorizzate sono state impostate su un valore iniziale.

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)")
}

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

Module is Optional("Failable Initializers")

Sostituzione di un inizializzatore non riuscito

Come per l'inizializzazione, l'utente ha anche la possibilità di sovrascrivere un inizializzatore non riuscito di superclasse all'interno della sottoclasse. L'inizializzazione non riuscita della super classe può anche essere sovrascritta in un inizializzatore non fallibile della sottoclasse.

L'inizializzatore della sottoclasse non può delegare l'inizializzatore della superclasse quando sovrascrive un inizializzatore della superclasse non riuscita con un'inizializzazione della sottoclasse non fallibile.

Un inizializzatore non fallibile non può mai delegare a un inizializzatore non riuscito.

Il programma fornito di seguito descrive gli inizializzatori non guasti e non guasti.

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)
   }
}

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

Planet name is: Mercury
No Planets like that: [No Planets]

L'init! Inizializzatore non riuscito

Swift 4 fornisce "init?" per definire un inizializzatore non riuscito dell'istanza facoltativa. Per definire un'istanza facoltativa implicitamente scartata del tipo specifico 'init!' è specificato.

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")
}

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

Student name is specified
Student name is left blank

Inizializzatori richiesti

Per dichiarare ogni sottoclasse della parola chiave initialize 'required' deve essere definita prima della funzione init ().

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()

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

10
30
10

Prima che un'istanza di classe debba essere deallocata, è necessario chiamare "deinitializer" per deallocare lo spazio di memoria. La parola chiave "deinit" viene utilizzata per deallocare gli spazi di memoria occupati dalle risorse di sistema. La deinizializzazione è disponibile solo sui tipi di classe.

Deinizializzazione per deallocare lo spazio di memoria

Swift 4 rilascia automaticamente le istanze quando non sono più necessarie, per liberare risorse. Swift 4 gestisce la gestione della memoria delle istanze tramite il conteggio automatico dei riferimenti (ARC), come descritto in Conteggio automatico dei riferimenti. In genere non è necessario eseguire la pulizia manuale quando le istanze vengono deallocate. Tuttavia, quando si lavora con le proprie risorse, potrebbe essere necessario eseguire da soli alcune pulizie aggiuntive. Ad esempio, se crei una classe personalizzata per aprire un file e scrivervi alcuni dati, potresti dover chiudere il file prima che l'istanza della classe venga deallocata.

var counter = 0; // for reference counting
class baseclass {
   init() {
      counter++;
   }
   deinit {
      counter--;
   }
}
var print: baseclass? = baseclass()

print(counter)
print = nil
print(counter)

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

1
0

Quando l'istruzione print = nil viene omessa, i valori del contatore rimangono gli stessi poiché non è deinizializzato.

var counter = 0; // for reference counting

class baseclass {
   init() {
      counter++;
   }
   deinit {
      counter--;
   }
}
var print: baseclass? = baseclass()
print(counter)
print(counter)

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

1
1

Le funzioni di gestione della memoria e il suo utilizzo vengono gestiti nel linguaggio Swift 4 tramite il conteggio automatico dei riferimenti (ARC). ARC viene utilizzato per inizializzare e deinizializzare le risorse di sistema rilasciando così gli spazi di memoria utilizzati dalle istanze della classe quando le istanze non sono più necessarie. ARC tiene traccia delle informazioni sulle relazioni tra le nostre istanze di codice per gestire efficacemente le risorse di memoria.

Funzioni di ARC

  • ARC alloca un pezzo di memoria per memorizzare le informazioni ogni volta che una nuova istanza di classe viene creata da init ().

  • Le informazioni sul tipo di istanza e sui relativi valori vengono archiviate in memoria.

  • Quando l'istanza di classe non è più necessaria, libera automaticamente lo spazio di memoria tramite deinit () per ulteriore archiviazione e recupero dell'istanza di classe.

  • ARC tiene traccia delle proprietà, delle costanti e delle variabili delle istanze di classe attualmente referenti in modo che deinit () venga applicato solo a quelle istanze inutilizzate.

  • ARC mantiene un "forte riferimento" a quelle proprietà, costanti e variabili dell'istanza di classe per limitare la deallocazione quando l'istanza di classe è attualmente in uso.

Programma ARC

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)

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

Swift 4
98

Istanze di classe di cicli di riferimento ARC Strong

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

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

Initializing: Swift 4
Initializing: ARC

Riferimenti ARC deboli e sconosciuti

Le proprietà del tipo di classe hanno due modi per risolvere i cicli di riferimento forti:

  • Riferimenti deboli
  • Riferimenti sconosciuti

Questi riferimenti vengono utilizzati per consentire a un'istanza di fare riferimento ad altre istanze in un ciclo di riferimento. Quindi le istanze possono fare riferimento a ciascuna istanza invece di preoccuparsi di un ciclo di riferimento forte. Quando l'utente sa che qualche istanza può restituire valori "nulli", possiamo indicarlo utilizzando un riferimento debole. Quando l'istanza restituirà qualcosa anziché nullo, dichiararlo con riferimento non proprietario.

Programma di riferimento debole

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

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

ARC Is The Main Module
Sub Module with its topic number is 4

Programma di riferimento sconosciuto

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

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

ARC
Marks Obtained by the student is 98

Forti cicli di riferimento per chiusure

Quando si assegna una chiusura alla proprietà di istanza della classe e al corpo della chiusura per acquisire un'istanza particolare, può verificarsi un forte ciclo di riferimento. Un forte riferimento alla chiusura è definito da 'self.someProperty' o 'self.someMethod ()'. I cicli di riferimento forti vengono utilizzati come tipi di riferimento per le chiusure.

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())

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

<p>Welcome to Closure SRC</p>

Riferimenti deboli e sconosciuti

Quando la chiusura e l'istanza si riferiscono l'una all'altra, l'utente può definire l'acquisizione in una chiusura come un riferimento non proprietario. Quindi non consentirebbe all'utente di deallocare l'istanza allo stesso tempo. Quando l'istanza a volte restituisce un valore 'nil', definire la chiusura con l'istanza debole.

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

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

<Inside>ARC Weak References</Inside>
Inside the deinit()

Il processo di interrogazione, chiamata di proprietà, pedici e metodi su un opzionale che può essere 'nil' è definito come concatenamento opzionale. Il concatenamento opzionale restituisce due valori:

  • se l'opzionale contiene un "valore", la chiamata alla sua proprietà correlata, metodi e pedici restituisce valori

  • se l'opzionale contiene un valore 'nil', tutte le sue proprietà, metodi e pedici correlati restituiscono nil

Poiché più query a metodi, proprietà e pedici sono raggruppati insieme, il fallimento di una catena influenzerà l'intera catena e darà come risultato un valore "nullo".

Concatenamento opzionale come alternativa allo srotolamento forzato

Il concatenamento facoltativo viene specificato dopo il valore facoltativo con "?" per chiamare una proprietà, un metodo o un pedice quando il valore facoltativo restituisce alcuni valori.

Concatenamento opzionale "?" Accesso a metodi, proprietà e pediciCatenamento opzionale "!" per forzare l'Unwrapping
? viene inserito dopo il valore opzionale per chiamare proprietà, metodo o pedice ! viene inserito dopo il valore facoltativo per chiamare proprietà, metodo o pedice per forzare lo scartamento del valore
Non riesce con grazia quando l'opzione è 'nil' Lo scartamento forzato innesca un errore di runtime quando l'opzione opzionale è 'nil'

Programma per il concatenamento opzionale con "!"

class ElectionPoll {
   var candidate: Pollbooth?
}

lass Pollbooth {
   var name = "MP"
}

let cand = ElectionPoll()
let candname = cand.candidate!.name

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

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

Il programma precedente dichiara "sondaggio elettorale" come nome della classe e contiene "candidato" come funzione di appartenenza. La sottoclasse viene dichiarata come "cabina di sondaggio" e "nome" come funzione di appartenenza che viene inizializzata come "MP". La chiamata alla super classe viene inizializzata creando un'istanza "cand" con opzionale "!". Poiché i valori non sono dichiarati nella sua classe base, il valore "nil" viene memorizzato restituendo un errore irreversibile dalla procedura di decompressione forzata.

Programma per concatenamento facoltativo con "?"

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")
}

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

Candidate name cannot be retreived

Il programma precedente dichiara "sondaggio elettorale" come nome della classe e contiene "candidato" come funzione di appartenenza. La sottoclasse viene dichiarata come "cabina di sondaggio" e "nome" come funzione di appartenenza che viene inizializzata come "MP". La chiamata alla super classe viene inizializzata creando un'istanza "cand" con opzionale "?". Poiché i valori non sono dichiarati nella sua classe base, il valore 'nil' viene memorizzato e stampato nella console dal blocco del gestore else.

Definizione di classi modello per concatenamento e accesso alle proprietà facoltativi

Il linguaggio Swift 4 fornisce anche il concetto di concatenamento opzionale, per dichiarare più di una sottoclassi come classi modello. Questo concetto sarà molto utile per definire modelli complessi e per accedere alle proprietà, ai metodi e alle proprietà secondarie dei pedici.

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")
}

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

Rectangle Area is not specified

Richiamo di metodi tramite concatenamento facoltativo

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")
}

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

Area of circle is not specified

La funzione circleprint () dichiarata all'interno della sottoclasse circle () viene chiamata creando un'istanza chiamata "circname". La funzione restituirà un valore se contiene un valore, altrimenti restituirà un messaggio di stampa definito dall'utente controllando l'istruzione 'if circname.print? .Circleprint ()! = Nil'.

Accesso agli indici tramite concatenamento facoltativo

Il concatenamento facoltativo viene utilizzato per impostare e recuperare un valore di pedice per convalidare se la chiamata a quel pedice restituisce un valore. "?" viene posto prima delle parentesi graffe del pedice per accedere al valore facoltativo del particolare pedice.

Programma 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.")
}

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

Radius is not specified.

Nel programma precedente i valori di istanza per la funzione di appartenenza "radiusName" non sono specificati. Quindi la chiamata del programma alla funzione restituirà solo un'altra parte mentre per restituire i valori dobbiamo definire i valori per la particolare funzione di appartenenza.

Programma 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.")
}

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

Radius is measured in Units.

Nel programma precedente, vengono specificati i valori di istanza per la funzione di appartenenza "radiusName". Quindi la chiamata del programma alla funzione ora restituirà valori.

Accesso a pedici di tipo facoltativo

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])

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

Optional(35)
Optional(78)
Optional(78)
Optional(101)
Optional(90)
Optional(44)
Optional(56)

È possibile accedere ai valori facoltativi per i pedici facendo riferimento ai loro valori in pedice. È possibile accedervi come pedice [0], pedice [1] ecc. I valori di pedice predefiniti per "raggio" vengono prima assegnati come [35, 45, 78, 101] e per "Cerchio" [90, 45, 56]] . Quindi i valori in pedice vengono modificati come Raggio [0] in 78 e Cerchio [1] in 45.

Collegamento di più livelli di concatenamento

È inoltre possibile collegare più sottoclassi con i suoi metodi, proprietà e pedici di super classe mediante concatenamento opzionale.

È possibile collegare più concatenamenti di optional -

Se il recupero del tipo non è facoltativo, il concatenamento facoltativo restituirà un valore facoltativo. Ad esempio, se String attraverso il concatenamento opzionale restituirà String? Valore

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.")
}

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

Radius is not specified.

Nel programma precedente, i valori di istanza per la funzione di appartenenza "radiusName" non sono specificati. Quindi, la chiamata del programma alla funzione restituirà solo un'altra parte mentre per restituire i valori dobbiamo definire i valori per la particolare funzione di appartenenza.

Se il tipo di recupero è già facoltativo, anche il concatenamento facoltativo restituirà un valore facoltativo. Ad esempio se String? Si accede tramite concatenamento opzionale restituirà String? Valore..

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.")
}

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

Radius is measured in Units.

Nel programma precedente, vengono specificati i valori di istanza per la funzione di appartenenza "radiusName". Quindi, la chiamata del programma alla funzione ora restituirà valori.

Concatenamento di metodi con valori di ritorno opzionali

Il concatenamento opzionale viene utilizzato anche per accedere ai metodi definiti delle sottoclassi.

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")
}

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

Area of circle is not specified

Per convalidare il tipo di istanza, entra in gioco "Type Casting" nella lingua di Swift 4. Viene utilizzato per verificare se il tipo di istanza appartiene a una particolare superclasse o sottoclasse o è definito nella propria gerarchia.

Il casting di tipo Swift 4 fornisce due operatori "is" per verificare il tipo di un valore e "as" e per eseguire il cast del valore del tipo su un tipo diverso. Il casting del tipo controlla anche se il tipo di istanza segue un particolare standard di conformità del protocollo.

Definizione di una gerarchia di classi

Il casting del tipo viene utilizzato per controllare il tipo di istanze per scoprire se appartiene a un particolare tipo di classe. Inoltre, controlla la gerarchia delle classi e le sue sottoclassi per controllare ed eseguire il cast di tali istanze per renderlo come una stessa gerarchia.

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)")

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

Instance physics is: solid physics
Instance equation is: Hertz
Instance physics is: Fluid Dynamics
Instance formulae is: Giga Hertz

Tipo di controllo

Il controllo del tipo viene eseguito con l'operatore "is". L'operatore di controllo del tipo "is" controlla se l'istanza appartiene a un particolare tipo di sottoclasse e restituisce "true" se appartiene a tale istanza, altrimenti restituirà "false".

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")

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

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

Il downcasting del tipo di sottoclasse può essere eseguito con due operatori (as? E as!). 'As?' restituisce un valore facoltativo quando il valore restituisce nil. Viene utilizzato per controllare il downcast riuscito.

'come!' restituisce lo scartamento forzato come discusso nel concatenamento opzionale quando il ribaltamento restituisce un valore nullo. Viene utilizzato per attivare l'errore di runtime in caso di errore di downcast

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)")
   }
}

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

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

Typecasting: Any and Any Object

La parola chiave "Any" viene utilizzata per rappresentare un'istanza che appartiene a qualsiasi tipo, inclusi i tipi di funzione.

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")
   }
}

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

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

Per rappresentare l'istanza di qualsiasi tipo di classe, viene utilizzata la parola chiave "AnyObject".

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")
   }
}

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

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

È possibile aggiungere funzionalità di una classe, struttura o tipo di enumerazione esistente con l'aiuto di estensioni. La funzionalità del tipo può essere aggiunta con le estensioni, ma non è possibile sovrascrivere la funzionalità con le estensioni.

Swift Extension Functionalities -

  • Aggiunta di proprietà calcolate e proprietà di tipo calcolate
  • Definizione di metodi di istanza e tipo.
  • Fornire nuovi inizializzatori.
  • Definizione di pedici
  • Definizione e utilizzo di nuovi tipi annidati
  • Rendere un tipo esistente conforme a un protocollo

Le estensioni vengono dichiarate con la parola chiave "extension"

Sintassi

extension SomeType {
   // new functionality can be added here
}

Il tipo esistente può anche essere aggiunto con estensioni per renderlo uno standard di protocollo e la sua sintassi è simile a quella delle classi o delle strutture.

extension SomeType: SomeProtocol, AnotherProtocol {
   // protocol requirements is described here
}

Proprietà calcolate

Le proprietà "istanza" e "tipo" calcolate possono anche essere estese con l'aiuto di estensioni.

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)")

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

Addition is 103
Subtraction is 110
Multiplication is 390
Division is 11
Mixed Type is 154

Inizializzatori

Swift 4 offre la flessibilità di aggiungere nuovi inizializzatori a un tipo esistente tramite estensioni. L'utente può aggiungere i propri tipi personalizzati per estendere i tipi già definiti e sono anche possibili ulteriori opzioni di inizializzazione. Le estensioni supportano solo init (). deinit () non è supportato dalle estensioni.

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)")

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

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)

Metodi

Nuovi metodi di istanza e metodi di tipo possono essere aggiunti ulteriormente alla sottoclasse con l'aiuto delle estensioni.

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")
})

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

Inside Extensions Block
Inside Extensions Block
Inside Extensions Block
Inside Extensions Block
Inside Type Casting Block
Inside Type Casting Block
Inside Type Casting Block

La funzione topics () accetta un argomento di tipo '(summation: () → ())' per indicare che la funzione non accetta argomenti e non restituirà alcun valore. Per chiamare quella funzione più volte, for block viene inizializzata e la chiamata al metodo con topic () viene inizializzata.

Metodi di istanza mutanti

I metodi di istanza possono anche essere modificati quando dichiarati come estensioni.

I metodi di struttura ed enumerazione che modificano self o le sue proprietà devono contrassegnare il metodo dell'istanza come mutante, proprio come i metodi mutanti da un'implementazione originale.

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)")

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

Area of circle is: 34.210935
Area of circle is: 105.68006
Area of circle is: 45464.070735

Pedici

Anche l'aggiunta di nuovi pedici a istanze già dichiarate può essere possibile con le estensioni.

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])

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

2
6
5

Tipi annidati

I tipi annidati per istanze di classe, struttura ed enumerazione possono anche essere estesi con l'aiuto di estensioni.

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])

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

10
20
30
40
50
50

I protocolli forniscono un modello per metodi, proprietà e altre funzionalità dei requisiti. È semplicemente descritto come uno scheletro di metodi o proprietà invece di implementazione. L'implementazione di metodi e proprietà può essere ulteriormente eseguita definendo classi, funzioni ed enumerazioni. La conformità di un protocollo è definita come i metodi o le proprietà che soddisfano i requisiti del protocollo.

Sintassi

I protocolli seguono anche la sintassi simile a quella di classi, strutture ed enumerazioni -

protocol SomeProtocol {
   // protocol definition 
}

I protocolli vengono dichiarati dopo i nomi dei tipi di classe, struttura o enumerazione. Sono anche possibili dichiarazioni di protocollo singolo e multiplo. Se vengono definiti più protocolli, devono essere separati da virgole.

struct SomeStructure: Protocol1, Protocol2 {
   // structure definition 
}

Quando un protocollo deve essere definito per la super classe, il nome del protocollo deve seguire il nome della super classe con una virgola.

class SomeClass: SomeSuperclass, Protocol1, Protocol2 {
   // class definition 
}

Requisiti di proprietà e metodo

Il protocollo viene utilizzato per specificare una particolare proprietà del tipo di classe o proprietà dell'istanza. Specifica solo il tipo o la proprietà dell'istanza invece di specificare se si tratta di una proprietà archiviata o calcolata. Inoltre, viene utilizzato per specificare se la proprietà è "gettabile" o "impostabile".

I requisiti di proprietà sono dichiarati dalla parola chiave "var" come variabili di proprietà. {get set} è usato per dichiarare proprietà gettabili e impostabili dopo la loro dichiarazione di tipo. Gettabile è menzionato dalla proprietà {get} dopo la dichiarazione del tipo.

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)

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

98
true
false
Swift 4 Protocols
Swift 4

Requisiti del metodo mutante

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()

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

Wednesday

Requisiti dell'inizializzatore

Swing consente all'utente di inizializzare i protocolli per seguire la conformità del tipo simile a quella dei normali inizializzatori.

Sintassi

protocol SomeProtocol {
   init(someParameter: Int)
}

Per esempio

protocol tcpprotocol {
   init(aprot: Int)
}

Implementazioni di classe dei requisiti dell'inizializzatore di protocollo

Designato o inizializzatore di convenienza consente all'utente di inizializzare un protocollo per conformarsi al suo standard tramite la parola chiave riservata "obbligatoria".

class SomeClass: SomeProtocol {
   required init(someParameter: Int) {
      // initializer implementation statements
   }
}

protocol tcpprotocol {
   init(aprot: Int)
}

class tcpClass: tcpprotocol {
   required init(aprot: Int) {
   }
}

La conformità del protocollo è assicurata su tutte le sottoclassi per l'implementazione esplicita o ereditata dal modificatore "obbligatorio".

Quando una sottoclasse sovrascrive il suo requisito di inizializzazione della super classe, viene specificata dalla parola chiave del modificatore 'override'.

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)")

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

res is: 20
res is: 30
res is: 50

Protocolli come tipi

Invece di implementare funzionalità in un protocollo, vengono utilizzate come tipi per funzioni, classi, metodi ecc.

È possibile accedere ai protocolli come tipi in -

  • Funzione, metodo o inizializzazione come parametro o tipo restituito

  • Costante, variabile o proprietà

  • Array, dizionari o altri contenitori come elementi

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}))

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

10
20
30
5
10
15
[100, 200, 300]
[10, 20, 30]

Aggiunta della conformità al protocollo con un'estensione

Il tipo esistente può essere adottato e conformato a un nuovo protocollo facendo uso di estensioni. Nuove proprietà, metodi e pedici possono essere aggiunti ai tipi esistenti con l'aiuto di estensioni.

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"
      }
   }
}

Ereditarietà del protocollo

Swift 4 consente ai protocolli di ereditare le proprietà dalle sue proprietà definite. È simile a quella dell'ereditarietà delle classi, ma con la scelta di elencare più protocolli ereditati separati da virgole.

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)

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

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

Protocolli di sola classe

Quando i protocolli sono definiti e l'utente vuole definire il protocollo con le classi, questo dovrebbe essere aggiunto definendo prima la classe seguita dall'elenco di ereditarietà del protocollo.

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)")

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

res is: 20
res is: 30
res is: 50

Composizione del protocollo

Swift 4 consente di chiamare più protocolli contemporaneamente con l'aiuto della composizione del protocollo.

Sintassi

protocol<SomeProtocol, AnotherProtocol>

Esempio

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)

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

Person(name: "Priya", age: 21)
Person(name: "Rehan", age: 29)
Person(name: "Roshan", age: 19)

Verifica della conformità del protocollo

La conformità del protocollo viene verificata da operatori "is" e "as" simili a quelli del casting di tipo.

  • L'operatore is restituisce true se un'istanza è conforme allo standard del protocollo e restituisce false se fallisce.

  • Il as? la versione dell'operatore downcast restituisce un valore facoltativo del tipo di protocollo e questo valore è nullo se l'istanza non è conforme a quel protocollo.

  • La versione as dell'operatore downcast impone il downcast al tipo di protocollo e attiva un errore di runtime se il downcast non riesce.

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")
   }
}

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

Area is 12.5663708
Area is 198.0
Rectangle area is not defined

Il linguaggio Swift 4 fornisce funzionalità "Generiche" per scrivere funzioni e tipi flessibili e riutilizzabili. I generici vengono utilizzati per evitare duplicazioni e fornire astrazioni. Le librerie standard di Swift 4 sono costruite con codice generico. I tipi "Arrays" e "Dictionary" di Swift 4s appartengono a raccolte generiche. Con l'aiuto di array e dizionari, gli array sono definiti per contenere i valori "Int" e "String" o qualsiasi altro tipo.

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)")

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

Before Swapping values are: 100 and 200
After Swapping values are: 200 and 100

Funzioni generiche: parametri di tipo

Le funzioni generiche possono essere utilizzate per accedere a qualsiasi tipo di dati come "Int" o "String".

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)")

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

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

La funzione exchange () è usata per scambiare i valori che è descritto nel programma sopra e <T> è usato come parametro di tipo. Per la prima volta, la funzione exchange () viene chiamata per restituire i valori "Int" e la seconda chiamata alla funzione exchange () restituirà i valori "String". È possibile includere più tipi di parametri all'interno delle parentesi angolari separate da virgole.

I parametri di tipo sono denominati come definiti dall'utente per conoscere lo scopo del parametro di tipo che contiene. Swift 4 fornisce <T> come nome di parametro di tipo generico. Tuttavia, i parametri di tipo come array e dizionari possono anche essere denominati come chiave, valore per identificare che appartengono al tipo "Dizionario".

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()

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

[Swift 4]
[Swift 4, Generics]
[Swift 4, Generics, Type Parameters]
[Swift 4, Generics, Type Parameters, Naming Type Parameters]

Estensione di un tipo generico

L'estensione della proprietà dello stack per conoscere la parte superiore dell'elemento è inclusa con la parola chiave "extension".

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).")
}

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

["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.

Vincoli di tipo

Il linguaggio Swift 4 consente ai "vincoli di tipo" di specificare se il parametro di tipo eredita da una classe specifica o di garantire lo standard di conformità del protocollo.

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)")

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

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

Tipi associati

Swift 4 consente di dichiarare i tipi associati all'interno della definizione del protocollo mediante la parola chiave "associatedtype".

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)

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

[Swift 4]
[Swift 4, Generics]
[Swift 4, Generics, Type Parameters]
[Swift 4, Generics, Type Parameters, Naming Type Parameters]

Dove clausole

I vincoli di tipo consentono all'utente di definire requisiti sui parametri di tipo associati a una funzione o tipo generico. Per la definizione dei requisiti per i tipi associati, le clausole "where" sono dichiarate come parte dell'elenco dei parametri di tipo. La parola chiave 'where' viene posizionata immediatamente dopo l'elenco dei parametri di tipo seguito dai vincoli dei tipi associati, dalle relazioni di uguaglianza tra i tipi e dai tipi associati.

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)

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

[Swift 4]
[Swift 4, Generics]
[Swift 4, Generics, Where Clause]
[Swift 4, Generics, Where Clause]

Per limitare l'accesso a blocchi di codice, moduli e astrazione viene eseguito tramite il controllo degli accessi. È possibile accedere a classi, strutture ed enumerazioni in base alle loro proprietà, metodi, inizializzatori e pedici tramite meccanismi di controllo dell'accesso. Costanti, variabili e funzioni in un protocollo sono limitate e consentito l'accesso come globale e locale attraverso il controllo dell'accesso. Il controllo dell'accesso applicato a proprietà, tipi e funzioni può essere definito "entità".

Il modello di controllo dell'accesso si basa su moduli e file di origine.

Il modulo è definito come una singola unità di distribuzione del codice e può essere importato utilizzando la parola chiave "import". Un file sorgente è definito come un singolo file di codice sorgente con in un modulo per accedere a più tipi e funzioni.

Tre diversi livelli di accesso sono forniti dalla lingua Swift 4. Sono accesso pubblico, interno e privato.

S.No Livelli di accesso e definizione
1

Public

Consente alle entità di essere elaborate con qualsiasi file sorgente dal loro modulo di definizione, un file sorgente da un altro modulo che importa il modulo di definizione.

2

Internal

Consente alle entità di essere utilizzate all'interno di qualsiasi file sorgente dal loro modulo di definizione, ma non in alcun file sorgente al di fuori di quel modulo.

3

Private

Limita l'uso di un'entità al proprio file sorgente di definizione. L'accesso privato gioca il ruolo di nascondere i dettagli di implementazione di una funzionalità di codice specifica.

Sintassi

public class SomePublicClass {}
internal class SomeInternalClass {}
private class SomePrivateClass {}

public var somePublicVariable = 0
internal let someInternalConstant = 0
private func somePrivateFunction() {}

Controllo degli accessi per i tipi di funzione

Alcune funzioni possono avere argomenti dichiarati all'interno della funzione senza alcun valore di ritorno. Il seguente programma dichiara aeb come argomenti della funzione sum (). All'interno della funzione stessa i valori per gli argomenti aeb vengono passati invocando la chiamata di funzione sum () ei suoi valori vengono stampati eliminando così i valori di ritorno. Per rendere privato il tipo restituito dalla funzione, dichiarare il livello di accesso complessivo della funzione con il modificatore 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)

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

30 20
50 40
30 24

Controllo di accesso per i tipi di enumerazione

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).")
   
}

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

Student Marks are: 98,97,95

L'enumerazione nella lingua Swift 4 riceve automaticamente lo stesso livello di accesso per i singoli casi di un'enumerazione. Si consideri ad esempio per accedere al nome degli studenti e ai voti assicurati in tre materie il nome dell'enumerazione è dichiarato come studente e i membri presenti nella classe enum sono il nome che appartiene al tipo di dati stringa, i voti sono rappresentati come segno1, segno2 e segno3 del tipo di dati Integer. Per accedere al nome dello studente o ai voti che hanno ottenuto. Ora, il caso dello switch stamperà il nome dello studente se quel blocco del caso viene eseguito altrimenti stamperà i voti assicurati dallo studente. Se entrambe le condizioni falliscono, verrà eseguito il blocco predefinito.

Controllo degli accessi per le sottoclassi

Swift 4 consente all'utente di sottoclassare qualsiasi classe a cui è possibile accedere nel contesto di accesso corrente. Una sottoclasse non può avere un livello di accesso più alto della sua superclasse. L'utente non può scrivere una sottoclasse pubblica di una superclasse interna.

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()

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

Welcome to Swift Super Class
Welcome to Swift Sub Class

Controllo dell'accesso per costanti, variabili, proprietà e pedici

La costante, la variabile o la proprietà di Swift 4 non può essere definita pubblica rispetto al suo tipo. Non è valido scrivere una proprietà pubblica con un tipo privato. Allo stesso modo, un pedice non può essere più pubblico del suo indice o tipo restituito.

Quando una costante, una variabile, una proprietà o un pedice utilizza un tipo privato, anche la costante, la variabile, la proprietà o il pedice devono essere contrassegnati come privati:

private var privateInstance = SomePrivateClass()

Getters e Setter

Getter e setter per costanti, variabili, proprietà e pedici ricevono automaticamente lo stesso livello di accesso della costante, variabile, proprietà o pedice a cui appartengono.

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

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

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

Controllo dell'accesso per inizializzatori e inizializzatori predefiniti

Agli inizializzatori personalizzati può essere assegnato un livello di accesso inferiore o uguale al tipo che inizializzano. Un inizializzatore richiesto deve avere lo stesso livello di accesso della classe a cui appartiene. I tipi di parametri di un inizializzatore non possono essere più privati ​​del livello di accesso dello stesso inizializzatore.

Per dichiarare ogni sottoclasse della parola chiave initialize 'required' deve essere definita prima della funzione init ().

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()

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

10
30
10

Un inizializzatore predefinito ha lo stesso livello di accesso del tipo che inizializza, a meno che quel tipo non sia definito come pubblico. Quando l'inizializzazione predefinita è definita come pubblica, viene considerata interna. Quando l'utente necessita che un tipo pubblico sia inizializzabile con un inizializzatore senza argomenti in un altro modulo, fornire esplicitamente un inizializzatore pubblico senza argomenti come parte della definizione del tipo.

Controllo degli accessi per i protocolli

Quando definiamo un nuovo protocollo per ereditare le funzionalità da un protocollo esistente, entrambi devono essere dichiarati gli stessi livelli di accesso per ereditare le proprietà l'uno dell'altro. Il controllo degli accessi di Swift 4 non consentirà agli utenti di definire un protocollo "pubblico" che eredita da un protocollo "interno".

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)")

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

res is: 20
res is: 30
res is: 50

Controllo degli accessi per le estensioni

Swift 4 non consente agli utenti di fornire un modificatore del livello di accesso esplicito per un'estensione quando l'utente utilizza tale estensione per aggiungere la conformità del protocollo. Il livello di accesso predefinito per ciascuna implementazione dei requisiti di protocollo all'interno dell'estensione viene fornito con il proprio livello di accesso al protocollo.

Controllo degli accessi per i generici

I generici consentono all'utente di specificare i livelli di accesso minimi per accedere ai vincoli di tipo sui suoi parametri di tipo.

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()

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

[Swift 4]
[Swift 4, Generics]
[Swift 4, Generics, Type Parameters]
[Swift 4, Generics, Type Parameters, Naming Type Parameters]

Controllo dell'accesso per gli alias di tipo

L'utente può definire alias di tipo per trattare tipi di controllo di accesso distinti. Lo stesso livello di accesso o diversi livelli di accesso possono essere definiti dall'utente. Quando l'alias di tipo è "privato", i membri associati possono essere dichiarati come "privato, interno di tipo pubblico". Quando l'alias di tipo è pubblico, i membri non possono essere alias come nome "interno" o "privato"

Tutti gli alias di tipo definiti dall'utente vengono trattati come tipi distinti ai fini del controllo dell'accesso. Un alias di tipo può avere un livello di accesso inferiore o uguale al livello di accesso del tipo alias. Ad esempio, un alias di tipo privato può alias un tipo privato, interno o pubblico, ma un alias di tipo pubblico non può alias un tipo interno o privato.

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)

Quando eseguiamo il programma precedente usando playground, otteniamo il seguente risultato:

[Swift 4]
[Swift 4, Generics]
[Swift 4, Generics, Where Clause]
[Swift 4, Generics, Where Clause]

Codifica e decodifica rapide

Swift 4 introduce un nuovo Codable Protocollo, che consente di serializzare e de-serializzare i tipi di dati personalizzati senza scrivere alcun codice speciale e senza doversi preoccupare di perdere i tipi di valore.

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

Si noti che Langauage è conforme al protocollo codificabile. Ora lo convertiremo in una rappresentazione dei dati Json usando una semplice riga.

let encoder = JSONEncoder()
if let encoded = try? encoder.encode(java) {
   //Perform some operations on this value.
}

Swift codificherà automaticamente tutti i valori all'interno del tuo tipo di dati.

È possibile decodificare i dati utilizzando la funzione Decoder come

let decoder = JSONDecoder()
if let decoded = try? decoder.decode(Language.self, from: encoded) {
   //Perform some operations on this value.
}

Sia JSONEncoder che la sua controparte dell'elenco delle proprietà PropertyListEncoder hanno molte opzioni per personalizzare il loro funzionamento.