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
非常感谢帮助。
我们将使用更缩小的示例(如下)来阐明此处出现的问题。然而,关键 "error" 是 Case
不能为 ... where T: NSManagedObject, I: AnyObject
使用 objectWithId()
的默认实现;因为类型 Int
不符合类型约束 AnyObject
。后者用于表示 class 类型的实例,而 Int
是 value 类型。
AnyObject
can represent an instance of any class type.
Any
can represent an instance of any type at all, including function types.
来自Language Guide - Type casting.
随后,Case
无法访问蓝图 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
扩展到 T
则不符合 AnyObject
,因为 Int
不符合 [=75] =]-型一般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
可以访问 ... where T: NSManagedObject, I: AnyObject
的 objectWithId()
默认实现,因为 NSNumber
是 class 类型,符合 AnyObject
.
最后,请注意上面的示例,关键字 override
不需要实现协议中蓝图的方法(例如,上面示例中的 entityName()
方法)。 Case
的扩展是一个协议扩展(通过实现蓝图类型和方法来符合 ObjectByIdFetchable
),并不能真正与 super[= 的 subclassing Case
相提并论75=](在这种情况下,您可能希望重写 superclass 方法)。
我找到了问题的解决方案。我认为这是类型别名 T 这是不编译的原因。这其实不是真的,是我对 AnyObject 说的,有趣的是 Int 不是 AnyObject。我不得不将 Int 更改为 NSNumber
我正在尝试通过协议向 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
非常感谢帮助。
我们将使用更缩小的示例(如下)来阐明此处出现的问题。然而,关键 "error" 是 Case
不能为 ... where T: NSManagedObject, I: AnyObject
使用 objectWithId()
的默认实现;因为类型 Int
不符合类型约束 AnyObject
。后者用于表示 class 类型的实例,而 Int
是 value 类型。
AnyObject
can represent an instance of any class type.
Any
can represent an instance of any type at all, including function types.
来自Language Guide - Type casting.
随后,Case
无法访问蓝图 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
扩展到 T
则不符合 AnyObject
,因为 Int
不符合 [=75] =]-型一般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
可以访问 ... where T: NSManagedObject, I: AnyObject
的 objectWithId()
默认实现,因为 NSNumber
是 class 类型,符合 AnyObject
.
最后,请注意上面的示例,关键字 override
不需要实现协议中蓝图的方法(例如,上面示例中的 entityName()
方法)。 Case
的扩展是一个协议扩展(通过实现蓝图类型和方法来符合 ObjectByIdFetchable
),并不能真正与 super[= 的 subclassing Case
相提并论75=](在这种情况下,您可能希望重写 superclass 方法)。
我找到了问题的解决方案。我认为这是类型别名 T 这是不编译的原因。这其实不是真的,是我对 AnyObject 说的,有趣的是 Int 不是 AnyObject。我不得不将 Int 更改为 NSNumber