0

NSManagedObject我正在尝试通过协议向 an 添加功能。我添加了一个可以正常工作的默认实现,但是一旦我尝试使用协议扩展我的子类,它就会告诉我它的某些部分没有实现,即使我添加了默认实现。

有人知道我做错了什么吗?

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

2 回答 2

4

我们将使用一个更按比例缩小的示例(如下)来阐明这里出了什么问题。然而,关键的“错误”是Case不能使用 for 的默认objectWithId()实现... where T: NSManagedObject, I: AnyObject;因为类型Int不符合类型约束AnyObject。后者用于表示类型的实例,而是Int类型

AnyObject可以表示任何类类型的实例。

Any可以表示任何类型的实例,包括函数类型。

语言指南 - 类型转换

随后,Case无法访问蓝图objectWithId()方法的任何实现,因此不符合协议ObjectByIdFetchable


Footo 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")
    }
}

但是,对于扩展FooT符合 :s 的情况并非如此AnyObject,因为Int它不符合类类型 general 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可以访问 for 的默认实现objectWithId()... where T: NSManagedObject, I: AnyObject就像NSNumber类类型一样,它符合AnyObject.


最后,从上面的示例中请注意,override实现协议中蓝图的方法不需要关键字(例如,entityName()上面示例中的方法)。的扩展是一个协议扩展(通过实现蓝图类型和方法Case来符合),并且不能与超类的子类化相比(在这种情况下,您可能想要覆盖超类方法)。ObjectByIdFetchableCase

于 2016-02-13T14:35:02.533 回答
0

我找到了问题的解决方案。我认为是 typealias T 是不编译的原因。这其实不是真的,我对AnyObject说的是I,有趣的是Int不是AnyObject。我不得不将 Int 更改为 NSNumber

于 2016-02-13T14:40:44.883 回答