簡體   English   中英

Swift中協議擴展的默認實現不起作用

[英]Default implementation of protocol extension in Swift not working

我正在嘗試通過協議將功能添加到NSManagedObject 我添加了一個可以正常工作的默認實現,但是當我嘗試使用該協議擴展子類時,即使我添加了默認實現,它也會告訴我它的某些部分尚未實現。

任何人都知道我在做什么錯?

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

非常感謝幫助。

我們將使用一個更按比例縮小的示例(下),以闡明此處出了什么問題。 但是,關鍵的“錯誤”是Case無法為... where T: NSManagedObject, I: AnyObject使用默認的objectWithId()實現... where T: NSManagedObject, I: AnyObject ; 因為類型Int不符合類型約束AnyObject 后者用於表示類型的實例,而Int類型。

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

Any可以代表任何類型的實例,包括函數類型。

語言指南類型轉換

隨后, Case無法訪問blueprinted objectWithId()方法的任何實現,因此不符合協議ObjectByIdFetchable


Foo默認擴展名T :s符合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")
    }
}

但是,對於將Foo擴展到符合AnyObject T :s而言,情況並非如此,因為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類類型。


最后,請注意上述示例中的關鍵字override ,對於實現協議中設計的方法(例如,上述示例中的entityName()方法entityName()是不需要的。 Case的擴展是協議的擴展(通過實現藍圖類型和方法符合ObjectByIdFetchable ),並不能真正與超類對Case的子類進行比較(在這種情況下,您可能要覆蓋超類的方法)。

我找到了解決問題的辦法。 我以為是typealias T就是不編譯的原因。 這實際上是不對的,我對AnyObject說的是我,有趣的是Int不是AnyObject。 我必須將Int更改為NSNumber

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM