我是静态类型语言的新手,并想知道是否可以将Struct转换为其类型以调用正确的重载函数?我遇到的问题是我有一个符合Mutation
协议的Structs列表。我想迭代列表并为每个Struct调用正确的handle
函数。我可以将这个handle
函数移动到Struct本身,但是对于我试图实现的API,我想看看是否可以这样做:
//: Playground - noun: a place where people can play
import UIKit
protocol Mutation {
func mutate(state: Int) -> Int
}
struct CountIncrement: Mutation {
func mutate(state: Int) -> Int {
return state + 1
}
}
struct CountDecrement: Mutation {
func mutate(state: Int) -> Int {
return state - 1
}
}
func handle(mutation: CountIncrement, state: Int) -> Int {
print("WILL INCREMENT")
return mutation.mutate(state: state)
}
func handle(mutation: CountDecrement, state: Int) -> Int {
print("WILL DECREMENT")
return mutation.mutate(state: state)
}
var state = 0
var queue = [CountIncrement(), CountDecrement()] as [Mutation]
for mutation in queue {
handle(mutation: mutation, state: state) // error: cannot invoke 'handle' with an argument list of type '(mutation: Mutation, state: Int)'
}
答案 0 :(得分:1)
您可以合并handle()
这样的函数,并接受参数mutation
符合您的协议Mutation
的所有对象:
func handle(mutation: Mutation, state: Int) -> Int {
return mutation.mutate(state: state)
}
原因是:
queue
属于[Mutating]
类型。因此,您的for-Loop中的mutation
将为Mutation
。目前,您没有handle()
函数,它接受Mutation
作为参数。
答案 1 :(得分:1)
这是你应该如何解决问题的倒退。在Swift中,您通常应该避免使用自由函数(例如-56dp
),而是将方法附加到类型。
你的循环想要一个特定的方法,所以你想要一个新的协议(你当然可以将这个功能附加到handle(mutation:state:)
,但是将它分开意味着它可以有不同的访问控制等,所以就像灵活的自由功能)。
Mutation
所以我们刚刚声明你想要的这个功能就是一个东西。现在我们可以将它附加到我们关心的事物上。这与您在上面编写自由函数完全相同。它是相同的模式。语法不同,并提供了一些关于此函数存在的额外文档,并允许IDE更有效地提供自动完成和收集文档。
protocol MutationHandling {
func handleMutation(forState state: Int) -> Int
}
现在,您将此特殊协议用于您的列表:
extension CountIncrement: MutationHandling {
func handleMutation(forState state: Int) -> Int {
print("WILL INCREMENT")
return mutate(state: state)
}
}
并称之为:
var queue = [CountIncrement(), CountDecrement()] as [MutationHandling]
这不仅仅是Swift中的一些随机限制。这是Swift如何分解问题的重要部分。明确不鼓励使用自由函数(参见API Design Guidelines)。方法和扩展是Swift方式。