有没有一种方法可以在函数指针中设置协议的数据类型?

时间:2019-04-09 18:37:06

标签: swift types protocols

有没有一种方法可以在功能指针中快速设置协议的数据类型?

这是我的协议ICRUDOperation

public protocol ICRUDOperation {
    associatedtype T
    func insert(data:T)
    func update(data:T)
    func get(data:T) -> [T]
    func getList(data: BaseModel) -> [T]
    func getPage(data: BaseModel) -> [T]
    func delete(data: T)
}

我尝试在其中使用:

func delegate1<W>(sqlite: W, service: W, data: W.T) where W: ICRUDOperation {
    sqlite.insert(data: data)
}
var decision = [String : [String:((ICRUDOperation, ICRUDOperation, T) ->())?]]()

func fillDecision() {
    decision["Person"]?["1"] = Delegate1
}

我在决策中遇到此错误

Protocol 'ICRUDOperation' can only be used as a generic constraint because it has Self or associated type requirements

fillDecision()的错误:

Cannot assign value of type '(_, _, _.T) -> ()' to type '((ICRUDOperation, ICRUDOperation, _) -> ())??'

2 个答案:

答案 0 :(得分:1)

一旦添加了关联类型,就不再存在“ ICRUDOperation”之类的东西。 PAT(具有关联类型的协议)没有存在形式;它的存在是为了将方法附加到 other 类型,或限制可以将哪些具体类型传递给泛型函数。您不能将PAT存储在变量或字典中或其他任何位置。协议(并且是双倍的PAT)不是抽象类。

要理解的最关键的事情是关联类型是由实现选择的,而不是由调用方选择的。因此,在您的示例中,T将通过ICRUDOperation的实现进行选择(与Array选择其Collection.Index为Int的方式相同;您不必选择它)。泛型允许调用方选择类型,该类型看起来更像您要实现的目标。

如何解决此问题取决于您的用例,这很难从您的示例中理解。 decision的目标是什么?

如果您演示预期的ICRUDOperation的两种或三种不同实现,将很有帮助。我不确定“操作的实现”是什么意思。

答案 1 :(得分:0)

我试图了解您如何使用此协议,因此这是我如何使用协议的想法。我不确定这是否能回答您的问题,但也许可以帮助您更接近解决方案。
说我们有一个我们要坚持的模型

struct Item {
    var id: Int
    var name: String
}

然后我们需要一个可以执行db操作的处理程序

struct ItemDbHandler: ICRUDOperation {
    typealias T = Item

    func insert(data: Item) {
        print("\(#function) \(item)")
    }

    func update(data: Item) {
        print("\(#function) \(item)")
    }

    func get(data: Item) -> [Item] { //shouldn't this return 1 element
        print("\(#function) \(item)")
        return []
    }
    // and so on...
}

并带有一些委托函数

func delegateUpdate<W>(sqlite: W, service: W, data: W.T) where W: ICRUDOperation {
    sqlite.update(data: data)
}

我们可以直接使用处理程序,也可以通过函数使用

var item = Item(id: 1, name: "ABC")
var handler = ItemDbHandler()
handler.insert(data: item)
item.name = "abc"

delegateUpdate(sqlite: handler, service: handler, data: item)

在操场上跑步会产生收益

  

插入(数据:)项(id:1,名称:“ ABC”)
  update(data :) Item(id:1,name:“ abc”)

我不知道你想做什么fillDecision,所以我暂时跳过了。