快速类自省与泛型

我试图使用泛型动态创建一个基于 class实例的类型,但是我遇到了类自省的困难。

下面是一些问题:

  • 有没有一个类似于 Obj-C 的 self.class的 Swift?
  • 有没有一种方法可以使用来自 NSClassFromStringAnyClass结果来实例化一个类?
  • 有没有办法从泛型参数 T严格获得 AnyClass或其他类型的信息?(类似于 C # 的 typeof(T)语法)
64636 次浏览

首先,Swift 等价的 [NSString class].self(参见 元型文件,尽管它们非常薄)。

事实上,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 执行失败: error: : 16:1: error: 构造一个类型为‘ X’、具有元类型值的对象需要一个‘@ 需要’初始值设定项

 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在操场上给了我一个错误。

如果我正在阅读文档,如果你处理实例,例如想返回一个新的实例,与你已经给出的对象类型相同,类型可以用 init ()构造,你可以这样做:

let typeOfObject = aGivenObject.dynamicType
var freshInstance = typeOfObject()

我很快用 String 测试了一下:

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

效果不错。

终于有东西可以工作了,虽然有点懒,但是即使是 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")

and bingo, "makeFoo" contains a Foo instance.

缺点是您的类必须从 FactoryObject 派生,并且它们必须具有 Obj-C + initialize 方法,因此您的类将通过全局函数“ mapClass”自动插入到类映射中。

以下是如何使用 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 猛击名称; 这是至关重要的,因为否则我们不知道指定每个类的猛击字符串。

现在我们可以使用 NSClassFromString来创建 Zork 类或 Zilk 类,因为我们知道我们可以将它作为 NSObject 类型输入,而不会在以后崩溃:

let aClass = NSClassFromString("Zork") as NSObject.Type
let anObject = aClass()
println(anObject) // "I am a Zork"

它是可逆的; println(NSStringFromClass(anObject.dynamicType))也可以工作。


现代版:

    if let aClass = NSClassFromString("Zork") as? NSObject.Type {
let anObject = aClass.init()
print(anObject) // "I am a Zork"
print(NSStringFromClass(type(of:anObject))) // Zork
}

Here is another example showing class hierarchy implementation, similar to accepted answer, updated for the first release of 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

Swift implementation of comparing 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

注意: 注意,它也可以使用对象可以扩展或不可以扩展的协议

In 雨燕3

object.dynamicType

不推荐。

取而代之的是:

type(of:object)