来自AnyObject的Swift,Self

时间:2014-09-18 23:25:57

标签: ios swift

是否可以从AnyObject获取Self?

举个例子:

// Superclass
class ManagedObject {
  class func findByID(id: String) -> AnyObject? {
    let objects = objectsWithPredicate(NSPredicate(format: "id == %@", id))
    return objects.firstObject() // Returns AnyObject
  }
}

// Subclass
class User : ManagedObject {
  class func returnFirstSelf() -> Self? {
    return findById("1") // This doesn't work because it returns AnyObject, but I need Self.
  }
}

如果没有,确保在调用User.returnFirstSelf()时,编译器返回User的最佳替代方法是什么,并且在调用UserSubclass.returnFirstSelf()时,它会返回{{1} }}

2 个答案:

答案 0 :(得分:4)

如果这是一个选项,您只需从类函数返回User?

public class func returnFirstSelf() -> User? {
    if let found = findByID("1") as? User {
        return found
    }
    return nil
}

目前无法(我知道)使用Swift返回Self?。问题是Self具有某种......“动态”含义,与具体类型,协议甚至泛型分开。演示此问题的一个特定示例是:如果您的课程StudentUser延伸User怎么办?如果你试图像这样实现它:

class func returnFirstSelf() -> Self? {
    if let found = findById("1") as? Self { // Note the check that 'found' is a 'Self'
        return found
    }
    return nil
}

然后您遇到编译器错误,因为您不能在协议或类方法的结果之外使用Self。如果你试图像这样实现它:

class func returnFirstSelf() -> Self? {
    if let found = findById("1") as? User { // Note 'User' instead of 'Self'
        return found
    }
    return nil
}

然后您冒Self实际意味着StudentUser的风险,即使您通过了需要found成为User的支票,也不能保证found将是StudentUser。如果StudentUser未覆盖该方法以确保as?检查StudentUser,则会发生这种情况。

我认为这里的关键缺陷是你不能在类方法上使用required关键字,要求子类覆盖它们。这将允许编译器确保任何子类覆盖该方法并提供可以保证类型安全的实现。

答案 1 :(得分:0)

克雷格奥蒂斯'回答是现货。但是,一种选择是创建一个复制构造函数。这可能不适用于他们从NSManagedObject继承的提问者场景,但它应该适用于非托管对象。

required init(user: User) {
    super.init(user: User) // or super.init() if top of inheritance.
    self.name = user.name
    self.email = user.email
    // etc.
}

class func returnFirstSelf() -> Self? {
    if let found = findById("1") { // Note the check that 'found' is a 'Self'
        return self.init(copy: found as! User)
    }
    return nil
}