J'essaye de créer dynamiquement un class
type basé sur instance en utilisant des génériques, mais je rencontre des difficultés avec l'introspection de classe.
Voici les questions:
- Y a-t-il un équivalent Swift aux Obj-C
self.class
? - Existe-t-il un moyen d'instancier une classe en utilisant le
AnyClass
résultat deNSClassFromString
? - Existe-t-il un moyen d'obtenir
AnyClass
ou de taper des informations strictement à partir d'un paramètre génériqueT
? (Similaire à latypeof(T)
syntaxe de C # )
introspection
swift
Erik
la source
la source
self.class
deviendraitself.dynamicType.self
dans la croyance Swift Iself.dynamicType.foo()
Réponses:
Eh bien, d'une part, l'équivalent Swift de
[NSString class]
is.self
(voir la documentation Metatype , bien qu'elle soit assez mince).En fait,
NSString.class
ça ne marche même pas! Vous devez utiliserNSString.self
.De même, avec une classe rapide, j'ai essayé ...
Hmm… l'erreur dit:
Il m'a fallu un certain temps pour comprendre ce que cela signifie ... il s'avère qu'il veut que la classe ait un
@required init()
Certains documents appellent cela
.Type
, maisMyClass.Type
me donne une erreur dans la cour de récréation.la source
.Type
ou.Protocol
dans la déclaration de variable, par exemplelet myObject: MyObject.Type = MyObject.self
@
avantrequired
devrait être suppriméVoici comment l'utiliser
NSClassFromString
. Vous devez connaître la superclasse avec laquelle vous allez vous retrouver. Voici une paire superclasse-sous-classe qui sait se décrire pourprintln
:Notez l'utilisation de la
@obj
syntaxe spéciale pour dicter le nom en Objective-C de ces classes; c'est crucial, car sinon nous ne connaissons pas la chaîne munged qui désigne chaque classe.Maintenant, nous pouvons utiliser
NSClassFromString
pour créer la classe Zork ou la classe Zilk, car nous savons que nous pouvons le saisir en tant que NSObject et ne pas planter plus tard:Et c'est réversible;
println(NSStringFromClass(anObject.dynamicType))
fonctionne également.Version moderne:
la source
@objc(ClassName)
bit. Je connaissais l'@objc
attribut mais pas que vous puissiez également donner un indice sur le nom de la classe.as! NSObject.Type
dans la première ligne etaClass.init()
dans la secondeSi je lis bien la documentation, si vous traitez avec des instances et que vous voulez par exemple renvoyer une nouvelle instance du même type que l'objet que vous avez reçu et que le type peut être construit avec un init (), vous pouvez faire:
Je l'ai rapidement testé avec String:
qui a bien fonctionné.
la source
dynamicType
fonctionne comme je m'y attendais. Cependant, je n'ai pas pu comparer les types. La vraie grande utilisation est avec les génériques, donc je pourrais avoir quelque chose commeGeneric<T>
et à l'intérieurif T is Double {...}
. Il semble que ce ne soit pas possible par inadvertance.Defaultable
protocole qui fonctionne de manière similaire audefault
mot clé de C # , et des extensions appropriées pour les types commeString
etInt
. En ajoutant la contrainte générique deT:Defaultable
, je pourrais vérifier si l'argument est passéis T.default()
.value is String.default()
... etc, ce que vous finiriez par faire à lavalue is String
place.Dans Swift 3
est obsolète.
Utilisez plutôt:
la source
Implémentation rapide de la comparaison des types
REMARQUE: notez qu'il fonctionne également avec les protocoles que l'objet peut étendre ou non
la source
J'ai enfin quelque chose à travailler. C'est un peu paresseux mais même la route NSClassFromString () n'a pas fonctionné pour moi ...
et bingo, "makeFoo" contient une instance Foo.
L'inconvénient est que vos classes doivent dériver de FactoryObject et qu'elles DOIVENT avoir la méthode d'initialisation Obj-C + pour que votre classe soit automatiquement insérée dans la carte de classe par la fonction globale "mapClass".
la source
Voici un autre exemple montrant l'implémentation de la hiérarchie de classes, similaire à la réponse acceptée, mis à jour pour la première version de Swift.
Imprime ce résultat:
la source
var x: NamedItem.Type
, si je l'assignex = Folder.Type
,x()
renvoie un nouveauNamedItem
, pas unFolder
. Cela rend la technique inutile pour de nombreuses applications. Je considère cela comme un bug .