Differenza tra Generics e AnyObject in Swift

Considera questa function myFilter che accetta un argomento generico e filtra l'arrays in base al predicato. È uguale alla function filter() fornita da Swift.

 func myFilter<T>(source: [T], predicate:(T) -> Bool) -> [T] { var result = [T]() for i in source { if predicate(i) { result.append(i) } } return result } 

Come è diverso da

 func myFilter(source: [AnyObject], predicate:(AnyObject) -> Bool) -> [AnyObject] { var result = [AnyObject]() for i in source { if predicate(i) { result.append(i) } } return result } 

Non stiamo raggiungendo il punto di generici anche nel secondo esempio?

Solutions Collecting From Web of "Differenza tra Generics e AnyObject in Swift"

I generici sono sicuri per tipo, nel senso che se passi una string come generica e cerchi di usarla come un integer il compilatore si lamenterà e non sarai in grado di compilare il tuo (che è buono). (Questo accade perché Swift sta usando la tipizzazione statica ed è in grado di darti un errore del compilatore )

Se usi AnyObject il compilatore non ha idea se l'object può essere trattato come una string o come un integer. Ti permetterà di fare quello che vuoi con esso (che è male).

ad esempio, se provi a passare una string quando il tuo integer utilizzato in precedenza l'applicazione si blocca. (Questo accade perché Swift sta usando la digitazione dynamic e ti darà solo un crash in fase di esecuzione )

Generics dice fondamentalmente al compilatore:

"Ho intenzione di darti un tipo più tardi e voglio che tu imponga quel tipo ovunque io specifichi."

AnyObject in pratica dice al compilatore:

"Non preoccuparti di questa variabile, non è necessario applicare alcun tipo qui, lascia che faccia qualsiasi cosa desideri".

Nota : la risposta di Icaro sarebbe ancora la risposta accettata, sto solo estendendo la sua spiegazione.

TL; DR : Controlla la risposta di Icaro.

A proposito dell'uso di AnyObject Icaro mette giustamente:

Non preoccuparti di questa variabile, non è necessario applicare alcun tipo qui, lascia che faccia qualsiasi cosa desideri.

Cosa significa questo? Prendiamo l'esempio di codice nella domanda (ho fatto un passo avanti e AnyObject cambiato AnyObject su Any senza modificare il significato della domanda):

 func myFilter(source: [Any], predicate:(Any) -> Bool) -> [Any] { var result = [Any]() for i in source { if predicate(i) { result.append(i) } } return result } 

Ciò significa che la function myFilter accetta due argomenti una source e un predicate chiusura. Se si guarda da vicino, il contenuto dell'arrays sorgente può essere ANYTHING. E l'argomentazione del predicate chiusura può essere ANYTHING pure. Se wheressimo nominare questi "ANYTHING" s – diciamo ANYTHING1 e ANYTHING2 – questo approccio non richiede che ANYTHING1 sia uguale a ANYTHING2.

Sediamoci e riflettiamo sulle implicazioni di questo …

Diciamo, vogliamo filtrare gli altri da una serie di interi e usiamo il nostro filter Any per questo

 var ints = [1,2,3,4,5] as [Any] var predicate = { (a : Any) -> Bool in return (a as! Int) % 2 == 0 } let evens = myFilter(source: ints, predicate:predicate) 

Wow, ha funzionato, no? Tutti i sorrisi? No.

Nota come in linea:

 return (a as! Int) % 2 == 0 

Sto forzatamente down-casting a . Questa linea si bloccherebbe se a fosse qualcosa di diverso da un Int . Ma il suo utilizzo è giustificato; dopotutto, vogliamo solo filtrare l' Int s e io sono abbastanza intelligente da usare solo un arrays di Int s.

Ma, perché dire, io sono un ingenuo programmatore, lo faccio:

 var ints = [1,2,3,4,5,"6"] as [Any] var predicate = { (a : Any) -> Bool in return (a as! Int) % 2 == 0 } let evens = myFilter(source: ints, predicate:predicate) 

Compila felicemente, ma si arresta in modo anomalo nel runtime. Se solo ci fosse un modo, where il compilatore mi direbbe che questa linea …

 var ints = [1,2,3,4,5,"6"] 

… era difettoso, non avremmo avuto un incidente. L'avrei risolto subito!

Risulta, c'è. Generics. Per citare di nuovo Icaro,

Ho intenzione di darti un tipo più tardi e voglio che tu imponga quel tipo ovunque io specifichi.

 func myFilter<T>(source: [T], predicate:(T) -> Bool) -> [T] { var result = [T]() for i in source { if predicate(i) { result.append(i) } } return result } var ints = [1,2,3,4,5,6] var predicate = { (a : Int) -> Bool in return a % 2 == 0 } let evens = myFilter(source: ints, predicate:predicate) 

Questo nuovo filter è fantastico. Non mi lascerà fare:

let evens = myFilter(source: ints, predicate:predicate) perché, i tipi di predicate e source non corrispondono. Errore di compilazione del tempo.

Generics è generico in questo modo: in questo esempio specifico – mentre al punto di scrivere la function myFilter , non è necessario fornire un tipo di source o l'argomento che prende il predicate , è T, è ANYTHING. Ma una volta che dico che la source è una matrix di QUALSIASI COSA, devi assicurarti che l'argomento che il predicate accetta sia lo stesso QUALCHE COSA. Con lo background della nostra precedente nomenclatura ANYTHING1, ANYTHING2, possiamo dire che i generici costringono ANYTHING1 ad essere uguale a ANYTHING2

Considera che nella prima function T non è un tipo, come è AnyObject, ma una variabile di tipo ; ciò significa che nella prima function è ansible passare una matrix di valori di qualsiasi tipo come primo parametro, ma un predicato che opera solo su valori di quel tipo specifico come secondo parametro. È ansible passare una serie di stringhe e un predicato sulle stringhe o una matrix di numbers interi e un predicato sugli interi, mentre non è ansible passare una matrix di numbers interi e un predicato sulle stringhe. Quindi, il corpo della function è garantito per essere corretto per ciò che riguarda i tipi.

Invece nel secondo esempio è ansible passare un valore di qualsiasi tipo e un predicato che opera su qualsiasi tipo (possibilmente diverso!), In modo che, se il predicato venga chiamato nel corpo della function con il valore del primo parametro, quindi potrebbe verificarsi un errore di tipo dinamico. Fortunatamente, il tipografo Swith contrassegna la chiamata del predicato come errore di tipo, al fine di prevenire questa possibilità.