从Swift中的协议定义函数返回泛型

时间:2016-03-11 09:42:01

标签: swift generics realm

我声明了一个带有泛型函数的协议,但似乎在实现后类型推断无法正常工作。

protocol SearchableRealmModel {
    static func search<Self: Object>(needle: String) -> Results<Self>?
}

class Thing: Object, SearchableRealmModel {
    class func search<Thing>(needle: String) -> Results<Thing>? {
        return realm()?.objects(Thing).filter("name == '\(needle)'")
    }
}

let things = Thing.search("hello") // works but inferred type is Results<Object>?

此处的问题是things的推断类型为Results<Object>?。我意识到可以使用这些变化,

let things: Results<Thing>? = Thing.search("hello")
let things = Thing.search("hello") as Results<Thing>?

但每次必须指定类型是非常重复的。

在我的测试中,使用除Results<..>?之外的其他类型保持类型推断不变。这可能是因为必须在Self: Object中指定父类(由于Results而需要)。

感谢任何帮助。

1 个答案:

答案 0 :(得分:1)

这是Swift的仿制机器的限制。编译器可以生成static func search(needle: String) -> Results<Object>?的具体签名,该签名满足类型约束,因为Object子类将与此匹配。您可能会向bugs.swift.org提交错误,因为我认为Swift核心团队也会认为这是一个错误,如果不是非常意外的行为。

但是,您可以修改代码以使用协议扩展来执行您想要的操作:

protocol SearchableRealmModel {}

extension SearchableRealmModel where Self: Object {
    static func search(needle: String) -> Results<Self> {
        return try! Realm().objects(Self).filter("name == '\(needle)'")
    }
}

class Thing: Object, SearchableRealmModel {
    dynamic var name = ""
}

let result = Thing.search("thing1") // => inferred as Results<Thing>
print(result.first?.name)

如果你想为其他Realm模型自定义实现search,你可以重新实现那里的函数,编译器将优先考虑协议扩展版本:

class OtherThing: Object, SearchableRealmModel {
    dynamic var id = ""

    static func search(needle: String) -> Results<OtherThing> {
        return try! Realm().objects(OtherThing).filter("id == '\(needle)'")
    }
}