Introspection et génériques de classe rapide

J’essaie de créer dynamicment un type basé sur une instance de class utilisant des génériques, cependant je rencontre des difficultés avec l’introspection de classe.

Voici les questions:

  • Existe-t-il un équivalent Swift à la self.class d’Obj-C?
  • Est-il possible d’instancier une classe en utilisant le résultat NSClassFromSsortingng de NSClassFromSsortingng ?
  • Existe-t-il un moyen d’obtenir AnyClass ou de saisir des informations à partir d’un paramètre générique T ? (Similaire à la syntaxe typeof(T) de C #)

Eh bien, pour un, l’équivalent Swift de [NSSsortingng class] est .self (voir les documents Metatype , bien qu’ils soient plutôt fins).

En fait, NSSsortingng.class ne fonctionne même pas! Vous devez utiliser NSSsortingng.self .

 let s = NSSsortingng.self var str = s() str = "asdf" 

De même, avec une classe rapide, j’ai essayé …

 class MyClass { } let MyClassRef = MyClass.self // ERROR :( let my_obj = MyClassRef() 

Hmm… l’erreur dit:

L’exécution de Playground a échoué: erreur:: 16: 1: erreur: la construction d’un object de type de classe ‘X’ avec une valeur de métatype nécessite un initialiseur ‘@required’

  Y().me() ^ :3:7: note: selected implicit initializer with type '()' class X { ^ 

Il m’a fallu un moment pour comprendre ce que cela signifie… il s’avère que la classe doit avoir un @required init()

 class X { func me() { println("asdf") } required init () { } } let Y = X.self // prints "asdf" Y().me() 

Certains des documents se réfèrent à ceci comme .Type , mais MyClass.Type me donne une erreur dans la cour de récréation.

Voici comment utiliser NSClassFromSsortingng . Vous devez connaître la super-classe de ce que vous allez vous retrouver avec. Voici une paire de sous-classes superclasses qui sait se décrire pour println :

 @objc(Zilk) class Zilk : NSObject { override var description : Ssortingng {return "I am a Zilk"} } @objc(Zork) class Zork : Zilk { override var description : Ssortingng {return "I am a Zork"} } 

Notez l’utilisation de la syntaxe spéciale @obj pour dicter le nom @obj de l’objective-C de ces classes; c’est crucial, car sinon, nous ne connaissons pas la ficelle munie qui désigne chaque classe.

Maintenant, nous pouvons utiliser NSClassFromSsortingng pour créer la classe Zork ou la classe Zilk, car nous soaps que nous pouvons le taper comme un NSObject et ne pas planter plus tard:

 let aClass = NSClassFromSsortingng("Zork") as NSObject.Type let anObject = aClass() println(anObject) // "I am a Zork" 

Et c’est réversible; println(NSSsortingngFromClass(anObject.dynamicType)) fonctionne également.

Si je lis bien la documentation, si vous traitez des instances et que vous souhaitez par exemple renvoyer une nouvelle instance du même type que l’object que vous avez reçu et que Type peut être construit avec un init (), vous pouvez faire:

 let typeOfObject = aGivenObject.dynamicType var freshInstance = typeOfObject() 

Je l’ai rapidement testé avec Ssortingng:

 let someType = "Fooo".dynamicType let emptySsortingng = someType() let threeSsortingng = someType("Three") 

qui a bien fonctionné.

En swift 3

 object.dynamicType 

est déconseillé.

Au lieu de cela, utilisez:

 type(of:object) 

Mise en œuvre rapide des types de comparaison

 protocol Decoratable{} class A:Decoratable{} class B:Decoratable{} let object:AnyObject = A() object.dynamicType is A.Type//true object.dynamicType is B.Type//false object.dynamicType is Decoratable.Type//true 

NOTE: Notez que cela fonctionne aussi avec les protocoles que l’object peut ou ne peut pas étendre

Enfin eu quelque chose à travailler. C’est un peu paresseux mais même la route NSClassFromSsortingng () n’a pas fonctionné pour moi …

 import Foundation var classMap = Dictionary() func mapClass(name: Ssortingng, constructor: AnyObject) -> () { classMap[name] = constructor; } class Factory { class func create(className: Ssortingng) -> AnyObject? { var something : AnyObject? var template : FactoryObject? = classMap[className] as? FactoryObject if (template) { let somethingElse : FactoryObject = template!.dynamicType() return somethingElse } return nil } } import ObjectiveC class FactoryObject : NSObject { @required init() {} //... } class Foo : FactoryObject { class override func initialize() { mapClass("LocalData", LocalData()) } init () { super.init() } } var makeFoo : AnyObject? = Factory.create("Foo") 

et bingo, “makeFoo” contient une instance de Foo.

L’inconvénient est que vos classes doivent s’éloigner de FactoryObject et qu’elles DOIVENT avoir la méthode d’initialisation Obj-C + afin que votre classe soit automatiquement insérée dans la table de classes par la fonction globale “mapClass”.

Voici un autre exemple montrant l’implémentation de la hiérarchie de classes, similaire à la réponse acceptée, mise à jour pour la première version de Swift.

 class NamedItem : NSObject { func display() { println("display") } required override init() { super.init() println("base") } } class File : NamedItem { required init() { super.init() println("folder") } } class Folder : NamedItem { required init() { super.init() println("file") } } let y = Folder.self y().display() let z = File.self z().display() 

Imprime ce résultat:

 base file display base folder display