斯威夫特,从AnyObject

问题描述:

自我是有可能从AnyObject获得自我?斯威夫特,从AnyObject

拿这个例子:

// 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()时,还给一个UserSubclass

+1

遗憾的是没有。 “'Self'只在协议中或作为类方法的结果;您是否指'ManagedObject'?” – Baub 2014-09-18 23:32:54

+0

@BryanChen又导致了另一个错误“‘用户’是无法转换为‘自我’” – 2014-09-18 23:42:57

+0

什么是实现什么样的最佳方式?你能否更正式地解释一下你想做的事情? – matt 2014-09-18 23:52:52

你可以简单地从你的类函数返回User?,如果这是一个选项:

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

目前还没有任何办法(我知道的)同斯威夫特返回Self?因为它的立场。问题是Self有一些......“动态”的含义,与具体类型,协议甚至泛型分开。演示这一点的特定示例是:如果您有延伸User的类StudentUser,该怎么办?如果你想实现这样的:

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不覆盖的方法,以确保对StudentUseras?检查。

这里的关键缺陷在我看来,你不能在类方法中使用required关键字,需要子类来覆盖它们。这将允许编译器确保任何子类都重写了方法并提供了一个可以保证类型安全的实现。

+0

我在心灵感应@RobNapier。 – 2014-09-18 23:53:28

+0

谢谢克雷格。如果我创建ManagedObject'叫'Dog'的'子类 - 这意味着我不得不再次改写'returnFirstSelf()''下向Dog'做同样的事情,但具体到返回'Dog',而不是东西其他。这是我想要避免的。 – Baub 2014-09-19 00:05:46

+1

你说得对。尽管如此,这是一种选择。另一种选择是简单地返回'AnyObject?'从你的类func中获取,并且在你使用返回值的任何地方使用'if let'表达式来检查它们是否像你期望的那样是'Dog'类型。 – 2014-09-19 00:10:33

克雷格·奥的斯的答案是当场上。但是,一种选择是创建一个拷贝构造函数。这可能不适用于从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 
}