我正在尝试class
使用泛型动态创建基于实例的类型,但是我在类自省时遇到了困难。
这里是问题:
- 有一个Swift相当于Obj-C的
self.class
吗? - 有没有办法使用
AnyClass
from 的结果实例化一个类NSClassFromString
? - 有没有一种方法可以
AnyClass
严格从通用参数获取信息或以其他方式键入信息T
?(类似于C#的typeof(T)
语法)
self.class
将会成为self.dynamicType.self
Swift I的信念
我正在尝试class
使用泛型动态创建基于实例的类型,但是我在类自省时遇到了困难。
这里是问题:
self.class
吗?AnyClass
from 的结果实例化一个类NSClassFromString
?AnyClass
严格从通用参数获取信息或以其他方式键入信息T
?(类似于C#的typeof(T)
语法)self.class
将会成为self.dynamicType.self
Swift I的信念
Answers:
那么,对于一个,雨燕等同的[NSString class]
IS .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()
嗯...错误说:
游乐场执行失败:错误::16:1:错误:使用元类型值构造类类型为“ 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
在操场上却给我一个错误。
.Type
或.Protocol
在变量声明中使用,例如let myObject: MyObject.Type = MyObject.self
@
之前required
应删除
使用方法如下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
}
@objc(ClassName)
位。我知道该@objc
属性,但不知道还可以提供有关类名的提示。
as! NSObject.Type
第一排和aClass.init()
第二排
如果我没看错文档,如果您处理实例,例如想要返回与给定对象相同类型的新实例,并且可以使用init()构造类型,则可以执行以下操作:
let typeOfObject = aGivenObject.dynamicType
var freshInstance = typeOfObject()
我很快用String测试了它:
let someType = "Fooo".dynamicType
let emptyString = someType()
let threeString = someType("Three")
效果很好。
dynamicType
我在那工作了。但是,我无法比较类型。真正的大用途是使用泛型,因此我可以在Generic<T>
和里面放一些东西if T is Double {...}
。看来这不可能是不幸的。
Defaultable
类似于C#default
关键字的协议,并为诸如String
和等类型正确扩展Int
。通过添加的通用约束T:Defaultable
,我可以检查参数是否通过is T.default()
。
value is String.default()
...等操作,而最终只能这样做value is String
。
终于有了工作。它有点懒,但是即使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 + initialize方法,以便您的类通过全局函数“ 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
var x: NamedItem.Type
,如果我分配它x = Folder.Type
,则x()
返回一个新值NamedItem
,而不是Folder
。这使该技术对许多应用程序无用。我认为这是一个错误。