我尝试通过协议向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
非常感谢。
答案 0 :(得分:4)
我们将使用更简洁的示例(如下所示)来阐明这里出了什么问题。但是,关键的“错误”是Case
无法使用objectWithId()
的{{1}}的默认实现;因为类型... where T: NSManagedObject, I: AnyObject
不符合类型约束Int
。后者用于表示类类型的实例,而AnyObject
是值类型。
Int
可以表示任何类类型的实例。
AnyObject
可以表示任何类型的实例,包括函数类型。
来自Language Guide - Type casting。
随后,Any
无法访问blueprinted Case
方法的任何实现,因此不符合协议objectWithId()
。
符合ObjectByIdFetchable
的{{1}}到Foo
:s的默认扩展名有效,因为T
符合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")
}
}
:s符合Foo
的情况也是如此,因为T
不符合类型类通用{ {1}}:
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
的{{1}}的默认实现,因为typealias T = NSNumber
是类型,符合Case
。
最后,请注意上面的示例,实现协议中蓝图的方法(例如,上例中的objectWithId()
方法)不需要关键字... where T: NSManagedObject, I: AnyObject
。 NSNumber
的扩展名是一个协议扩展(通过实现蓝图类型和方法符合AnyObject
),并不能与超类的子类化override
相提并论(在这种情况下,您可能希望覆盖超类方法)。
答案 1 :(得分:0)
我找到了问题的解决方案。我认为这是typealias T,这是不编译的原因。这实际上不是真的,我是对AnyObject说的,有趣的是Int不是AnyObject。我不得不将Int更改为NSNumber