来自AnyObject的Swift,Self
是否有可能从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()
,它会返回一个UserSubclass
的最佳替代方法是UserSubclass
。
你可以简单地返回User?
从你的类函数,如果这是一个选项:
public class func returnFirstSelf() -> User? { if let found = findByID("1") as? User { return found } return nil }
目前还没有办法(我知道)回归Self?
与Swift一样。 问题在于Self
具有某种“动态”意义,与具体类型,协议甚至generics分开。 演示这一点的一个特定示例是:如果您有一个扩展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 }
然后你冒自己的风险实际上意味着StudentUser
,即使你通过了需要found
是User
的检查,它也不能保证found
将是StudentUser
。 这种情况会发生在StudentUser
没有覆盖方法以确保as?
检查StudentUser
。
在我看来, 这里的关键缺陷是你不能在类方法上使用required
关键字,要求子类覆盖它们。 这将允许编译器确保任何子类重写了该方法,并提供了一个可以保证类型安全的实现。
Craig Otis的回答很明显。 但是,一种选择是创建复制构造函数。 这可能不适用于提交者从NSManagedObjectinheritance的场景,但它应该适用于非托管对象。
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 }