2014-09-18 61 views
3

自我是有可能從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

回答

4

你可以簡單地從你的類函數返回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

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 
}