Swift中协议扩展的默认实现不起作用
我试图通过协议将功能添加到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
帮助非常赞赏。
我们将使用更多的按比例缩小的例子(见下文)对这里有什么不顺心线索。然而,关键的“错误”是Case
不能使用objectWithId()
的默认实现... where T: NSManagedObject, I: AnyObject
;因为类型Int
不符合类型约束AnyObject
。后者用来表示类类型的实例,而Int
是值类型。
AnyObject
可以表示任何类类型的实例。
Any
可以在所有代表任何类型的实例,包括功能类型。
从Language Guide - Type casting。
随后,Case
不能访问蓝图objectWithId()
方法的任何实现,因此不符合协议。
的Foo
到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")
}
}
同样是,但是,并不是真正用于扩展Foo
到T
:■符合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
没有真正的可比性。
我找到了解决问题的办法。我认为这是typealias T,这是不编译的原因。实际上这不是真的,这是我对AnyObject说的,有趣的是Int不是AnyObject。我不得不将Int更改为NSNumber
这是对的我得出了同样的结论,我用NSNumber替换Int并且它工作。 Any的问题是,它不符合VArgType,因此我不能将它用作谓词的参数。感谢您的好解释! –
@GeorgKitz乐于帮助! – dfri
@GeorgKitz那么,你能否简单地将你的泛型类型限制在我所在的位置:CVarArgType? –