通过绑定到超类,Swift子类采用自定义协议

时间:2017-10-31 17:31:55

标签: swift generics core-data

假设您有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 {}

这是一种正确的方法吗?

2 个答案:

答案 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