更新:问题和标题已根据对初始问题作出的更改进行了重述.
我有一个基类,它实现了用于创建新实例的泛型类方法.该类方法的简化逻辑如下
class MyBaseClass {
required init(_ record:MyRecordType) {
println("Entered MyBaseClass.init")
// Initialize base class from record
}
class func retrieveInstance<T:MyBaseClass>(name:String, callback:(T) -> ()) {
let myRecord:MyRecordType = ... // Perform fetch to get a record for name
let result = (T.self as T.Type)(myRecord) // Code currently crashes with BAD_ACCESS at this line
callback(result)
}
}
Run Code Online (Sandbox Code Playgroud)
然后,我使用如下所示的逻辑实现此基类的子类
class MySubClass : MyBaseClass {
required init(_ record:MyRecordType) {
println("Entered MySubClass.init")
// Initialize subclass from record
super.init(record)
}
}
Run Code Online (Sandbox Code Playgroud)
接下来,我尝试调用泛型类方法
class AnotherClass {
func successCallback(result:MySubclass) {
// Handle callback
}
MySubClass.retrieveInstance("objectName", callback:successCallback)
}
Run Code Online (Sandbox Code Playgroud)
在创建类的实例时 - 标有标记崩溃位置的注释的行 - 我期望MySubClass调用init方法.(这种奇怪的符号基于回复中建议的错误解决方法)
此代码不是调用init方法MySubClass,而是使用BAD_ACCESS崩溃.我一直无法找到任何可以解释此崩溃的零引用或其他任何内容.
在@rintaro最初发布的答案中得到了很多帮助,我能够解决这个问题,尽管我仍然会在一个单独的问题下发布一些奇怪的内容.
事实证明,使用以下语法初始化泛型类型的实例需要@rintaro是完全正确的:
let result = (T.self as T.Type)(myRecord)
Run Code Online (Sandbox Code Playgroud)
只要基类MyBaseClass使用required标记声明此初始化程序,这就可以工作:
public class MyBaseClass {
public required init(_ record:MyRecordType) {
...
}
}
Run Code Online (Sandbox Code Playgroud)
子类MySubClass实现匹配的初始化器:
public class MySubClass : MyBaseClass {
public required init (_ record:MyRecordType) {
...
super.init(record)
}
}
Run Code Online (Sandbox Code Playgroud)
然而,当事情失败时,我实际上有一个3级的类层次结构,初始化程序层次结构override通过混合.要想象这一点,请考虑一组表示树结构中节点的类:
public class Node {
public init(_ record:MyRecordType) {
...
}
}
public class RootNode : Node {
override public init(_ record:MyRecordType) {
...
super.init(record)
}
public class func <T:RootNode>retrieveAll(success:(T) -> ()) {
// Retrieve all instances of root node subclass T, and invoke success callback with new T instance
}
}
public class ChildNode : Node {
public init(_ record:MyRecordType, parentNode:Node) {
...
super.init(record)
}
public class func <T:ChildNode>retrieveChildren(parent:Node, success:(T) -> ()) {
// Retrieve all child T instances of parent node, and invoke success callback with new T instance
{
}
Run Code Online (Sandbox Code Playgroud)
问题发生在RootNode类的retrieveAll方法的实现中.为了使它像@rintaro所描述的那样工作,我需要用initin RootNode标记required关键字.但是因为它也覆盖了初始化器Node,所以它还需要有override关键字.所以我尝试在声明中使用两个关键字:
override required public init(_ record:MyRecordType) {
...
}
Run Code Online (Sandbox Code Playgroud)
Swift编译器接受这个,但是当我用它来从retrieveAll方法中初始化一个实例时,它会崩溃并发生BAD_ACCESS.
我能够通过NodeClass稍微改变方法签名来解决这个问题,以便它的RootNode子类不需要覆盖:
public class Node {
public init(record:MyRecordType) {
...
}
}
public class RootNode {
public required init(_ record:MyRecordType) {
...
super.init(record:record)
}
}
Run Code Online (Sandbox Code Playgroud)
通过执行此解决方法,我的子类RootNode可以正确实现所需的初始化程序,并且该retrieveAll方法RootNode可以正确地实例化这些子类的实例.
| 归档时间: |
|
| 查看次数: |
2357 次 |
| 最近记录: |