Estou tentando criar dinamicamente um class
tipo baseado em instância usando genéricos, mas estou tendo dificuldades com a introspecção de classe.
Aqui estão as perguntas:
- Existe um equivalente Swift aos Obj-C
self.class
? - Existe uma maneira de instanciar uma classe usando o
AnyClass
resultadoNSClassFromString
? - Existe uma maneira de obter
AnyClass
ou digitar informações estritamente de um parâmetro genéricoT
? (Semelhante àtypeof(T)
sintaxe do C # )
introspection
swift
Erik
fonte
fonte
self.class
se tornariaself.dynamicType.self
em Swift I crençaself.dynamicType.foo()
Respostas:
Bem, por um lado, o equivalente Swift de
[NSString class]
é.self
(consulte os documentos do Metatype , embora eles sejam muito finos).De fato,
NSString.class
nem funciona! Você tem que usarNSString.self
.Da mesma forma, com uma classe rápida, tentei ...
Hmm… o erro diz:
Levei um tempo para entender o que isso significa ... Acontece que ele quer que a classe tenha um
@required init()
Alguns dos documentos se referem a isso como
.Type
, masMyClass.Type
me dão um erro no playground.fonte
.Type
ou.Protocol
na declaração de variáveis, por exemplo:let myObject: MyObject.Type = MyObject.self
@
antesrequired
deve ser excluídoAqui está como usar
NSClassFromString
. Você precisa conhecer a superclasse do que vai acabar. Aqui estão um par de superclasse-subclasse que sabe como se descrever paraprintln
:Observe o uso da
@obj
sintaxe especial para ditar o nome munged Objective-C dessas classes; isso é crucial, porque, caso contrário, não conhecemos a string munged que designa cada classe.Agora podemos usar
NSClassFromString
para criar a classe Zork ou Zilk, porque sabemos que podemos digitá-lo como um NSObject e não travar mais tarde:E é reversível;
println(NSStringFromClass(anObject.dynamicType))
também funciona.Versão moderna:
fonte
@objc(ClassName)
pouco. Eu sabia sobre o@objc
atributo, mas não que você também pudesse dar uma dica sobre o nome da classe.as! NSObject.Type
na primeira linha eaClass.init()
na segundaSe estou lendo a documentação corretamente, se você lida com instâncias e, por exemplo, deseja retornar uma nova instância do mesmo tipo que o objeto que você recebeu e o tipo pode ser construído com um init (), você pode:
Eu rapidamente testei com String:
que funcionou bem.
fonte
dynamicType
funciona como eu esperava lá. No entanto, não consegui comparar tipos. O grande uso real é com genéricos, para que eu possa ter algo parecidoGeneric<T>
e internoif T is Double {...}
. Parece que isso não é possível, infelizmente.Defaultable
protocolo que funcione de maneira semelhante àdefault
palavra-chave do C # e extensões apropriadas para tipos comoString
eInt
. Adicionando a restrição genérica deT:Defaultable
, eu poderia verificar se o argumento foi aprovadois T.default()
.value is String.default()
... etc, o que você acabaria fazendovalue is String
.Em rápido 3
está obsoleto.
Em vez disso, use:
fonte
Implementação rápida de tipos de comparação
NOTA: Observe que ele também funciona com protocolos em que o objeto pode ou não estender
fonte
Finalmente tenho algo para trabalhar. É um pouco preguiçoso, mas mesmo a rota NSClassFromString () não funcionou para mim ...
e o bingo, "makeFoo" contém uma instância do Foo.
A desvantagem é que suas classes devem derivar do FactoryObject e DEVEM ter o método de inicialização do Obj-C + para que sua classe seja inserida automaticamente no mapa da classe pela função global "mapClass".
fonte
Aqui está outro exemplo que mostra a implementação da hierarquia de classes, semelhante à resposta aceita, atualizada para a primeira versão do Swift.
Imprime este resultado:
fonte
var x: NamedItem.Type
, se eu atribuí-lox = Folder.Type
,x()
retorna um novoNamedItem
, não umFolder
. Isso torna a técnica inútil para muitas aplicações. Eu considero isso um bug .