Como verificar duas instâncias são da mesma class / tipo em swift

Eu sei que eu posso verificar o tipo de um var em Swift com is

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

mas como posso verificar se duas instâncias têm a mesma class? O seguinte não funciona:

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

Eu poderia facilmente adicionar uma function “class” e atualizá-la em cada subclass para retornar algo único, mas isso parece um kludge …

Eu acho necessário citar a documentação da Swift Programming Language antes de tudo:

As classs possuem resources adicionais que as estruturas não :

  • A conversão de tipos permite verificar e interpretar o tipo de uma instância de class no tempo de execução.

De acordo com isso, pode ser útil para alguém no futuro:

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

e os testes:

 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 

ATUALIZAR

Você também pode sobrecarregar um novo operador para fazer uma coisa dessas, como por exemplo:

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

e os resultados:

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

ATUALIZAÇÃO # 2

você também pode usá-lo para suas próprias novas classs Swift , como por exemplo:

 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 

Eu também respondi Como você descobre o tipo de um object (no Swift)? para salientar que, em algum momento, a Apple adicionou suporte para o operador === aos tipos Swift, de modo que o seguinte funcionará agora:

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

Isso funciona mesmo sem importar o Foundation , mas observe que ele só funcionará para classs , já que as structs não possuem um tipo dynamic.

Swift 3.0 (também funciona com structs)

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

Swift 3 – preste atenção que comparar instâncias não é o mesmo que verificar se uma istance é de um determinado 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 

Eu estou usando isso, parece útil para mim: ele retorna true somente se todos os objects são do mesmo tipo;

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

No momento, os tipos Swift não têm introspecção, então não há uma maneira embutida de obter o tipo de uma instância. instance.className funciona para classs Objc.

Para subclasss de NSObject , eu fui com:

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

Outra ressalva desse método,

As subclasss privadas de um cluster de classs substituem o nome de sua superclass pública quando são arquivadas.

Documentação da Apple