假设您有NSManagedObject类层次结构。
class Dog: NSManagedObject {
var name: String?
}
class Person: NSManagedObject {
var name: String?
}
当然,您不希望重复代码。
你声明协议。
protocol Has_Name_Protocol {
var name: String? {get}
}
extension Has_Name_Protocol {
static func predicate(name: String?) -> NSPredicate {
return predicate(names: [name])
}
static func predicate(names: [String?]?) -> NSPredicate {
return NSPredicate(format: "name == %@", argumentArray: names?.flatMap({$0}))
}
}
当然,这还不够,你想引入搜索对象的find方法。
因此,您应该将协议绑定到适合的类层次结构中的最低边界。
extension Has_Name_Protocol where Self: NSManagedObject {
static func find(name: String?, context: NSManagedObjectContext) -> Self? {
return nil
}
}
还为符合此协议的子类添加扩展名。
extension Dog: Has_Name_Protocol {}
extension Person: Has_Name_Protocol {}
这是一种正确的方法吗?
答案 0 :(得分:1)
您可以添加Event KeyDown(e) -> keystate[e.KeyCode] = true
Event KeyUp(e) -> keystate[e.KeyCode] = false
并将其用作类型。为方便起见,您还需要添加associatedtype
。
考虑将entityType
声明为非可选。这避免了所有展开和平面映射。并制作name
方法find
并传递核心数据错误
未经测试的代码
throws
答案 1 :(得分:0)
当然,您不希望重复代码。
这不是使用协议的理由。 Protocols are more than a bag of syntax.您首先需要问“name
这些用法是否具有语义等价性,以便共享实现具有重要意义?”你不应该问“这些类包含同一组击键吗?”这可能是巧合,并不是合并它们的好理由,因为如果它们在语义上不同,它们可能会以不同的方式发展。
extension Has_Name_Protocol {
static func predicate(name: String?) -> NSPredicate {
return predicate(names: [name])
}
static func predicate(names: [String?]?) -> NSPredicate {
return NSPredicate(format: "name == %@", argumentArray: names?.flatMap({$0}))
}
}
这缺乏协议扩展中您想要的一致性。当String?
类型为name
时,为什么自然地传递String
?这创造了什么价值:
func predicate(property: String, values: [String]) -> NSPredicate {
return NSPredicate(format: "\(property) == %@", argumentArray: values)
}
func namePredicate(names: [String]) -> NSPredicate {
return predicate(property: "name", values: names)
}
这似乎只是为了改变语法,而不是创建一个有价值的抽象层。
static func find(name: String?, context: NSManagedObjectContext) -> Self?
此签名令人困惑。为什么name
是可选的?当你说过所有适用的东西必须有一个名字(这是协议的全部内容)时,“找到没有名字的东西”是什么意思?
如果您发现许多find
的实现在语法和语义上都相同,那么这里的基本概念很方便,但是我会强烈地问这些事情是否与“他们有更深的相似性”有一个名字。“如果这是他们唯一重要的相似之处,那么协议应该被称为Named
而不是Has_Name_Protocol
。