/// The protocol to which all types implicitly conform.
public typealias Any = protocol<>
Any
è solo un protocollo che tutti i tipi implicitamente conformi alle - non è un tipo di calcestruzzo stesso. Swift non può dedurre una matrice di tipi non concreti, che è il motivo per cui non riesce a dedurre Any
, ma riesce con NSObject
(Int
può essere colmato al NSNumber
, String
può essere colmato al NSString
- ed entrambi ereditano da NSObject
, che è una concreta genere).
Ad esempio, considerare questo:
protocol Foo {}
struct Bar:Foo {}
struct Baz:Foo {}
let arr = [Bar(), Baz()] // error: Type of expression is ambiguous without more context
Poiché Foo
è un tipo non-calcestruzzo, Swift non può dedurre un array di esso. Devi dire esplicitamente al compilatore ciò che si vuole il tipo di essere:
let arr:[Foo] = [Bar(), Baz()]
Avrete anche lo stesso comportamento con AnyObject
(come si tratta di un protocollo che tutti classi implicitamente conformi a -, ma ancora non è un tipo concreto):
class Qux {}
class Fox {}
let a = [Qux(), Fox()] // error: Type of expression is ambiguous without more context
let a1:[AnyObject] = [Qux(), Fox()] // no error
Perché Swift è in grado di dedurre una matrice di tipi non-cemento è più probabile a causa delle limitazioni esistenti di tipo non-concreto in lingua - attualmente tipi concreti sono necessari per la maggior parte operazioni non banali. See this great Q&A for an example.
Ma ad essere onesti, si dovrebbe davvero pensare di più sul fatto che si effettivamente bisogno di un array di Any
. Non riesco a pensare ad una singola applicazione pratica di avere una matrice di Any
, poiché tutto si conforma implicitamente agli elementi, essi devono essere sicuri di non fare nulla (non si può chiamare un metodo specifico su qualcosa che potrebbe essere qualsiasi cosa). Certo, puoi digitare il cast, ma qual è il punto nel recuperare la sicurezza del tipo che hai buttato via per cominciare?
Si dovrebbe sempre essere il tipo specifico che è possibile. Potresti creare un wrapper per i tuoi valori - questo potrebbe essere un semplice struct
per racchiudere un paio di proprietà, oppure un type erasure per racchiudere tipi non concreti in un tipo pseudo-concreto. Per lo meno, dovresti prendere in considerazione la creazione del tuo protocollo a cui gli elementi dell'array sono conformi.
Gli ultimi due paragrafi sollevano qui i punti più importanti. E onestamente, 'NSObject' (o' AnyObject' che non funzionerebbe qui ma lo vedo usato sempre) non è molto più specifico di 'Any'. – nhgrif
@ originaluser2 la tua spiegazione è davvero utile, grazie mille – c41ux
@ c41ux Felice di aiutare :) – Hamish