Swift类内省和generics
我试图dynamic创build一个基于class
实例使用generics,但是我遇到了类反思的困难。
以下是问题:
- 有没有一个相当于Obj-C的
self.class
的Swift? - 有没有办法使用
AnyClass
结果实例化一个类? - 有没有办法获得
AnyClass
或以其他方式严格从通用参数T
input信息? (类似于C#的typeof(T)
语法)
那么,作为一个, [NSString class]
的Swift等价物是.self
(请参阅Metatype文档 ,虽然它们很薄)。
事实上, NSString.class
甚至不工作! 你必须使用NSString.self
。
let s = NSString.self var str = s() str = "asdf"
同样的,一个快速的课我尝试…
class MyClass { } let MyClassRef = MyClass.self // ERROR :( let my_obj = MyClassRef()
嗯…错误说:
游乐场执行失败:错误::16:1:错误:构造types为“X”的对象具有元types值需要一个“@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名称; 这是至关重要的,因为否则我们不知道指定每个类的消逝的string。
现在我们可以使用NSClassFromString
来创buildZork类或Zilk类,因为我们知道我们可以将它作为一个NSObjectinput,而不会在以后崩溃:
let aClass = NSClassFromString("Zork") as NSObject.Type let anObject = aClass() println(anObject) // "I am a Zork"
而且是可逆的。 println(NSStringFromClass(anObject.dynamicType))
也可以。
如果我正在阅读文档,如果您处理实例并且想要返回与您已经提供的对象相同types的新实例,并且可以使用init()构造Type(types),那么您可以:
let typeOfObject = aGivenObject.dynamicType var freshInstance = typeOfObject()
我很快用String来testing它:
let someType = "Fooo".dynamicType let emptyString = someType() let threeString = someType("Three")
哪些工作正常。
在迅速3
object.dynamicType
已弃用。
而是使用:
type(of:object)
Swift实现比较types
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