2016-02-13 110 views
0

我試圖通過協議將功能添加到NSManagedObject。我添加了一個可以正常工作的默認實現,但只要我試圖用協議擴展我的子類,它就會告訴我它的一部分沒有實現,儘管我添加了默認實現。Swift中協議擴展的默認實現不起作用

任何人有我在做什麼想法錯誤?

class Case: NSManagedObject { 

} 

protocol ObjectByIdFetchable { 
    typealias T 
    typealias I 
    static var idName: String { get } 
    static func entityName() -> String 
    static func objectWithId(ids:[I], context: NSManagedObjectContext) -> [T] 
} 

extension ObjectByIdFetchable where T: NSManagedObject, I: AnyObject { 

    static func objectWithId(ids:[I], context: NSManagedObjectContext) -> [T] { 
     let r = NSFetchRequest(entityName: self.entityName()) 
     r.predicate = NSPredicate(format: "%K IN %@", idName, ids) 

     return context.typedFetchRequest(r) 
    } 
} 

extension Case: ObjectByIdFetchable { 

    typealias T = Case 
    typealias I = Int 

    class var idName: String { 
     return "id" 
    } 

    override class func entityName() -> String { 
     return "Case" 
    } 
} 

我得到的錯誤是Type Case doesn't conform to protocol ObjectByIdFetchable

幫助非常讚賞。

回答

4

我們將使用更多的按比例縮小的例子(見下文)對這裏有什麼不順心線索。然而,關鍵的「錯誤」是Case不能使用objectWithId()的默認實現... where T: NSManagedObject, I: AnyObject;因爲類型Int不符合類型約束AnyObject。後者用來表示類類型的實例,而Int類型。

AnyObject可以表示任何類類型的實例。

Any可以在所有代表任何類型的實例,包括功能類型。

Language Guide - Type casting

隨後,Case不能訪問藍圖objectWithId()方法的任何實現,因此不符合協議。


FooT默認的擴展名:■符合Any作品,因爲Int符合Any

protocol Foo { 
    typealias T 
    static func bar() 
    static func baz() 
} 

extension Foo where T: Any { 
    static func bar() { print ("bar") } 
} 

class Case : Foo { 
    typealias T = Int 

    class func baz() { 
     print("baz") 
    } 
} 

同樣是,但是,並不是真正用於擴展FooT:■符合AnyObject,如Int不符合類型普通AnyObject

protocol Foo { 
    typealias T 
    static func bar() 
    static func baz() 
} 

/* This will not be usable by Case below */ 
extension Foo where T: AnyObject { 
    static func bar() { print ("bar") } 
} 

/* Hence, Case does not conform to Foo, as it contains no 
    implementation for the blueprinted method bar() */ 
class Case : Foo { 
    typealias T = Int 

    class func baz() { 
     print("baz") 
    } 
} 

編輯此外:請注意,如果你改變(如你張貼在你自己的答案)

typealias T = Int 

typealias T = NSNumber 

然後自然Case訪問默認實現objectWithId()... where T: NSManagedObject, I: AnyObject,因爲NSNumber是類類型,它符合到AnyObject


最後,從以上所不需要用於實現在一個協議blueprinted方法關鍵字override實施例說明(例如,在你的例子entityName()方法上文)。 Case的擴展是一個協議擴展(通過實現藍圖類型和方法符合),並且與超類(在這種情況下,您可能想要重寫超類方法)對子類化Case沒有真正的可比性。

+1

這是對的我得出了同樣的結論,我用NSNumber替換Int並且它工作。 Any的問題是,它不符合VArgType,因此我不能將它用作謂詞的參數。感謝您的好解釋! –

+0

@GeorgKitz樂於幫助! – dfri

+0

@GeorgKitz那麼,你能否簡單地將你的泛型類型限制在我所在的位置:CVarArgType? –

0

我找到了解決問題的辦法。我認爲這是typealias T,這是不編譯的原因。實際上這不是真的,這是我對AnyObject說的,有趣的是Int不是AnyObject。我不得不將Int更改爲NSNumber

相關問題