Come verificare due istanze sono la stessa class / tipo in swift

So che posso controllare il tipo di una var in Swift con is

 if item is Movie { movieCount += 1 } else if item is Song { songCount += 1 } 

ma come posso verificare che due istanze abbiano la stessa class? Quanto segue non funziona:

 if item1 is item2.dynamicType { print("Same subclass") } else { print("Different subclass) } 

Potrei facilmente aggiungere una funzione di “class” e aggiornarla in ogni sottoclass per restituire qualcosa di unico, ma sembra un kludge …

Mi sento necessario citare prima di tutto la documentazione di Swift Programming Language :

Le classi hanno capacità aggiuntive che le strutture non hanno :

  • Il cast di tipo consente di controllare e interpretare il tipo di un’istanza di class in fase di runtime.

In base a ciò, potrebbe essere utile per qualcuno in futuro:

 func areTheySiblings(class1: AnyObject!, class2: AnyObject!) -> Bool { return object_getClassName(class1) == object_getClassName(class2) } 

e i test:

 let myArray1: Array = Array() let myArray2: Array = Array() let myDictionary: Dictionary = Dictionary() let myString: String = String() let arrayAndArray: Bool = self.areTheySiblings(myArray1, class2: myArray2) // true let arrayAndString: Bool = self.areTheySiblings(myArray1, class2: myString) // false let arrayAndDictionary: Bool = self.areTheySiblings(myArray1, class2: myDictionary) // false 

AGGIORNARE

puoi anche sovraccaricare un nuovo operatore per fare una cosa del genere, come ad esempio questo:

 infix operator >!< func >!< (object1: AnyObject!, object2: AnyObject!) -> Bool { return (object_getClassName(object1) == object_getClassName(object2)) } 

e i risultati:

 println("Array vs Array: \(myArray1 >!< myArray2)") // true println("Array vs. String: \(myArray1 >!< myString)") // false println("Array vs. Dictionary: \(myArray1 >!< myDictionary)") // false 

UPDATE # 2

puoi anche usarlo per le tue nuove classi Swift , come ad esempio quelle:

 class A { } class B { } let a1 = A(), a2 = A(), b = B() println("a1 vs. a2: \(a1 >!< a2)") // true println("a1 vs. b: \(a1 >!< b)") // false 

Ho anche risposto Come scopri il tipo di object (in Swift)? per sottolineare che ad un certo punto Apple ha aggiunto il supporto per l’operatore === a Swift Types, quindi ora funzionerà:

 if item1.dynamicType === item2.dynamicType { print("Same subclass") } else { print("Different subclass") } 

Funziona anche senza importare Foundation , ma nota che funzionerà solo per le classi , poiché le structs non hanno alcun tipo dinamico.

Swift 3.0 (funziona anche con le strutture)

 if type(of: someInstance) == type(of: anotherInstance) { print("matching type") } else { print("something else") } 

Swift 3 – fai attenzione che confrontare le istanze non equivale a controllare se un’istanza è di un determinato tipo:

 struct Model {} let modelLhs = Model() let modelRhs = Model() type(of: modelLhs) == type(of: modelRhs) //true type(of: modelLhs) == type(of: Model.self) //false modelLhs is Model //true 

sto usando questo, mi sembra utile: restituisce true solo se tutti gli oggetti sono dello stesso tipo;

 func areObjects(_ objects: [Any], ofType: T.Type) -> Bool { for object in objects { if !(object is T) { return false } } return true } 

Al momento i tipi Swift non hanno introspezione, quindi non esiste un modo integrato per ottenere il tipo di un’istanza. instance.className funziona per le classi Objc.

Per le sottoclassi di NSObject , sono andato con:

 let sameClass: Bool = instance1.classForCoder == instance2.classForCoder 

Un altro avvertimento su questo metodo,

Le sottoclassi private di un cluster di classi sostituiscono il nome della loro superclass pubblica quando vengono archiviate.

Documentazione Apple