Интроспекция и дженерики Swift

Я пытаюсь динамически создавать class основе экземпляра class с использованием дженериков, однако я сталкиваюсь с трудностями с самоанализом classа.

Вот вопросы:

  • Существует ли Swift-эквивалент self.class Obj-C?
  • Есть ли способ создать экземпляр classа с использованием результата NSClassFromString из NSClassFromString ?
  • Есть ли способ получить AnyClass или иначе напечатать информацию строго из общего параметра T ? (Подобно синтаксису типа C # typeof(T) )

    Ну, во- .self эквивалент Swift [NSString class].self (см. Документы Metatype , хотя они довольно тонкие).

    На самом деле, NSString.class даже не работает! Вы должны использовать NSString.self .

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

    Точно так же с быстрым classом я пробовал …

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

    Хм … ошибка говорит:

    Ошибка выполнения игровой площадки: ошибка:: 16: 1: ошибка: для построения объекта типа classа «X» с значением метатипа требуется инициализатор «@required»

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

    Мне потребовалось некоторое время, чтобы понять, что это значит … оказывается, он хочет, чтобы у classа был @required init()

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

    Некоторые из документов относятся к этому как .Type , но MyClass.Type дает мне ошибку на игровой площадке.

    Вот как использовать NSClassFromString . Вы должны знать суперclass о том, что у вас получится. Вот пара суперclassа-подclassа, который знает, как описать себя для 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 имя этих classов; это важно, потому что в противном случае мы не знаем строку, отмеченную каждым classом.

    Теперь мы можем использовать NSClassFromString чтобы сделать class Zork или class 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() 

    Я быстро протестировал его со String:

     let someType = "Fooo".dynamicType let emptyString = someType() let threeString = someType("Three") 

    который работал нормально.

    В быстрых 3

     object.dynamicType 

    не рекомендуется.

    Вместо этого используйте:

     type(of:object) 

    Быстрая реализация типов сравнения

     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() 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") 

    и bingo, «makeFoo» содержит экземпляр Foo.

    Недостатком является то, что ваши classы должны отвлекаться от FactoryObject, и они ДОЛЖНЫ иметь метод инициализации Obj-C +, чтобы ваш class автоматически включался в карту classов глобальной функцией «mapClass».

    Вот еще один пример, показывающий реализацию иерархии classов, аналогичный принятому ответу, обновленный для первого выпуска 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 
    Interesting Posts

    Что является самым элегантным способом конвертировать дефисное слово (например, «делать что-то») в более низкое изменение верблюжьего случая (например, «doSomeStuff»)?

    Как отключить Cortana в Windows 10 или, по крайней мере, отключить результаты веб-поиска (для других пользователей)?

    Действительно простое сжатие коротких строк

    Нет клавиши меню клавиатуры Windows, альтернативы?

    Сравнение типов с нулевым значением в Linq to Sql

    Как создать баланс аккаунта для всех пользователей в системе asterisk freePBX?

    Использование jQuery для построения строк таблицы из ответа Ajax (Json)

    OpenSSH, экран FreeBSD перезаписывается при закрытии приложения

    Как определить и установить основную графическую карту?

    Подключить Список к ListBox и увидеть изменения источника данных в ListBox

    Как открыть случайный файл в папке и установить, должны ли открываться только файлы с указанными расширениями имен файлов?

    Библиотека Bigint (bigbit)

    Как запустить Metro-приложение из командной строки в Windows 8?

    пакеты параметров шаблона доступа N-го типа и N-го элемента

    Как вводить зависимости в HttpSessionListener, используя Spring?

    Давайте будем гением компьютера.