Свифт классе самоанализ & дженериков
Я пытаюсь динамически создать class тип на основе экземпляра с использованием дженериков, однако я сталкиваюсь с трудностями с самоанализом класса.
вот вопросы:
- есть ли Swift-эквивалент Obj-C
self.class? - есть ли способ создать экземпляр класса с помощью
AnyClassв результатеNSClassFromString? - есть ли способ сделать
AnyClassили в противном случае введите информацию строго из общего параметраT? (Похоже на C# ' stypeof(T)синтаксис)
7 ответов:
Ну, во-первых, быстрый эквивалент
[NSString class]и.self(см. Metatype docs, хотя они довольно тонкие).в самом деле
NSString.classне работает! Вы должны использоватьNSString.self.let s = NSString.self var str = s() str = "asdf"точно так же, с быстрым классом я пробовал...
class MyClass { } let MyClassRef = MyClass.self // ERROR :( let my_obj = MyClassRef()Хм ... ошибка говорит:
Playground execution failed: error:: 16:1: error: построение объекта класса типа ' X ' со значением метатипа требует инициализатор '@required'
Y().me() ^ <REPL>:3:7: note: selected implicit initializer with type '()' class X { ^мне потребовалось некоторое время, чтобы понять, что это значит... оказывается, он хочет, чтобы класс имел
@required init()class X { func me() { println("asdf") } required init () { } } let Y = X.self // prints "asdf" Y().me()некоторые врачи относятся к этому как
.Type, аMyClass.Typeдает мне ошибку на детской площадке.
вот как использовать
NSClassFromString. Вы должны знать суперкласс того, что вы собираетесь в конечном итоге. Вот суперкласс-подкласс пара, которая знает, как описать себя дляprintln:@objc(Zilk) class Zilk : NSObject { override var description : String {return "I am a Zilk"} } @objc(Zork) class Zork : Zilk { override var description : String {return "I am a Zork"} }обратите внимание на использование специального
@objсинтаксис, чтобы диктовать Objective-C munged имя этих классов; это очень важно, потому что в противном случае мы не знаем munged строку, которая обозначает каждый класс.теперь мы можем использовать
NSClassFromStringчтобы сделать класс Zork или Zilk класс, потому что мы знаем, что мы можем ввести его как NSObject и не сбой позже:let aClass = NSClassFromString("Zork") as NSObject.Type let anObject = aClass() println(anObject) // "I am a Zork"и это обратимо;
println(NSStringFromClass(anObject.dynamicType))тоже работает.
Если я правильно читаю документацию, если вы имеете дело с экземплярами и, например, хотите вернуть новый экземпляр того же типа, что и объект, который вам был предоставлен, и тип может быть построен с помощью init() вы можете сделать:
let typeOfObject = aGivenObject.dynamicType var freshInstance = typeOfObject()я быстро проверил его с строку:
let someType = "Fooo".dynamicType let emptyString = someType() let threeString = someType("Three"), который работал хорошо.
быстрая реализация сравнения типов
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Примечание: заметить, что он также работает с протоколами объект может или не может продлить
наконец-то работать. Его немного ленивый, но даже маршрут NSClassFromString() не работал для меня...
import Foundation var classMap = Dictionary<String, AnyObject>() func mapClass(name: String, constructor: AnyObject) -> () { classMap[name] = constructor; } class Factory { class func create(className: String) -> 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")и бинго, "makeFoo" содержит экземпляр Foo.
недостатком является то, что ваши классы должны выводиться из FactoryObject, и они должны иметь метод инициализации Obj-C+, чтобы ваш класс автоматически вставлялся в карту класса глобальной функцией "mapClass".
вот еще один пример, показывающий реализацию иерархии классов, аналогичную принятому ответу, обновленному для первого выпуска 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()выводит такой результат:
base file display base folder display
Comments