实现相同协议的不同结构的重载函数?
Overload Functions For Different Structs Implementing The Same Protocol?
我是静态类型语言的新手,想知道是否可以将 Struct 转换为其类型以调用正确的重载函数?我 运行 遇到的问题是我有一个符合 Mutation
协议的结构列表。我想遍历列表并为每个 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)'
}
您可以像这样组合您的 handle()
函数并接受参数 mutation
所有符合您的协议的对象 Mutation
:
func handle(mutation: Mutation, state: Int) -> Int {
return mutation.mutate(state: state)
}
这样做的原因:
queue
属于 [Mutating]
类型。因此,您的 for 循环中的 mutation
将是 Mutation
。目前,您没有接受 Mutation
作为参数的 handle()
函数。
这与您解决问题的方式背道而驰。在 Swift 中,您通常应该避免自由函数(如 handle(mutation:state:)
),而是将方法附加到类型。
你的循环需要一个特定的方法,所以你需要一个新的协议(你当然可以把这个函数附加到 Mutation
,但是把它分开意味着它可以有不同的访问控制等等,所以和自由函数一样灵活)。
protocol MutationHandling {
func handleMutation(forState state: Int) -> Int
}
所以我们刚刚宣布您想要的这个功能是一个东西。现在我们可以将它附加到我们关心的事物上。这与您上面编写的自由函数完全相同。这是相同的模式。语法只是不同,并提供了一些额外的文档说明为什么存在此函数,并允许 IDE 提供自动完成功能并更有效地收集文档。
extension CountIncrement: MutationHandling {
func handleMutation(forState state: Int) -> Int {
print("WILL INCREMENT")
return mutate(state: state)
}
}
现在,您将此特殊协议用于您的列表:
var queue = [CountIncrement(), CountDecrement()] as [MutationHandling]
并称它为:
for mutation in queue {
mutation.handleMutation(forState: state)
}
这不仅仅是 Swift 中的一些随机限制。这是 Swift 如何分解问题的深层部分。明确不鼓励使用自由函数(参见 API Design Guidelines)。方法和扩展是 Swift 方式。
我是静态类型语言的新手,想知道是否可以将 Struct 转换为其类型以调用正确的重载函数?我 运行 遇到的问题是我有一个符合 Mutation
协议的结构列表。我想遍历列表并为每个 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)'
}
您可以像这样组合您的 handle()
函数并接受参数 mutation
所有符合您的协议的对象 Mutation
:
func handle(mutation: Mutation, state: Int) -> Int {
return mutation.mutate(state: state)
}
这样做的原因:
queue
属于 [Mutating]
类型。因此,您的 for 循环中的 mutation
将是 Mutation
。目前,您没有接受 Mutation
作为参数的 handle()
函数。
这与您解决问题的方式背道而驰。在 Swift 中,您通常应该避免自由函数(如 handle(mutation:state:)
),而是将方法附加到类型。
你的循环需要一个特定的方法,所以你需要一个新的协议(你当然可以把这个函数附加到 Mutation
,但是把它分开意味着它可以有不同的访问控制等等,所以和自由函数一样灵活)。
protocol MutationHandling {
func handleMutation(forState state: Int) -> Int
}
所以我们刚刚宣布您想要的这个功能是一个东西。现在我们可以将它附加到我们关心的事物上。这与您上面编写的自由函数完全相同。这是相同的模式。语法只是不同,并提供了一些额外的文档说明为什么存在此函数,并允许 IDE 提供自动完成功能并更有效地收集文档。
extension CountIncrement: MutationHandling {
func handleMutation(forState state: Int) -> Int {
print("WILL INCREMENT")
return mutate(state: state)
}
}
现在,您将此特殊协议用于您的列表:
var queue = [CountIncrement(), CountDecrement()] as [MutationHandling]
并称它为:
for mutation in queue {
mutation.handleMutation(forState: state)
}
这不仅仅是 Swift 中的一些随机限制。这是 Swift 如何分解问题的深层部分。明确不鼓励使用自由函数(参见 API Design Guidelines)。方法和扩展是 Swift 方式。