Swift 函数中可选泛型参数的默认值
Default value for optional generic parameter in Swift function
是否可以为可选的泛型参数提供默认值?
我正在尝试做这样的事情:
func addChannel<T>(name: String, data: T? = nil) -> Channel {
}
let myChannel = addChannel("myChannelName")
但我收到一条错误消息
Argument for generic parameter 'T' could not be inferred
这只是我想做的事情不可能的情况吗?
以你的方式是不可能的。仅给出上面的代码,T
是什么类型?正如它所说,编译器无法弄清楚(我也不能,我想你也不能,因为数据不存在)。
具体问题的解决方案是重载而不是使用默认值:
func addChannel<T>(name: String, data: T?) -> Channel { ... }
func addChannel(name: String) -> Channel { ... }
let myChannel = addChannel("myChannelName")
但它提出了你在这里做什么的问题。你会认为 Channel
应该是 Channel<T>
。否则,你用 data
做什么?如果不求助于 Any
(你应该强烈避免),很难看出你的函数除了忽略 data
.
还能做什么
使用 Channel<T>
您可以只使用默认值,但您必须提供类型:
func addChannel<T>(name: String, data: T? = nil) -> Channel<T> { ... }
let myChannel: Channel<Int> = addChannel("myChannelName")
否则编译器不知道你在制作什么样的频道。
(更新~Swift 5.2)
有时您想要 T
的默认类型。你可以通过重载来做到这一点。例如,您可能希望默认类型为 Never
。在这种情况下,您将添加这样的重载:
func addChannel<T>(name: String, data: T? = nil) -> Channel<T> { ... }
func addChannel(name: String) -> Channel<Never> {
addChannel(name: name, data: Optional<Never>.none)
}
有了它,您可以进行更简单的调用:
let myChannel = addChannel(name: "myChannelName") // Channel<Never>
我运行陷入同样的问题。虽然传统上不能使用通用默认值——完全不考虑参数——但我更喜欢下面的实现重载:
let myChannel=addChannel("myChannelName", data: Optional<Any>.none)
我使用了现有答案的组合,这样我既可以在没有可选参数的情况下调用函数,又可以避免执行函数两次。
func addChannel(name: String) -> Channel {
addChannel(name: name, data: Optional<Any>.nil)
}
func addChannel<T>(name: String, data: T? = nil) -> Channel {
...
}
如上所述,您应该避免 Any
。在我的例子中,我知道 T
是一个 Encodable
所以我使用这个:
struct DefaultEncodable: Encodable {}
func function1(name: String) {
addChannel(name: name, data: Optional<DefaultEncodable>.nil)
}
func function1<T: Encodable>(name: String, data: T? = nil) {
...
}
是否可以为可选的泛型参数提供默认值?
我正在尝试做这样的事情:
func addChannel<T>(name: String, data: T? = nil) -> Channel {
}
let myChannel = addChannel("myChannelName")
但我收到一条错误消息
Argument for generic parameter 'T' could not be inferred
这只是我想做的事情不可能的情况吗?
以你的方式是不可能的。仅给出上面的代码,T
是什么类型?正如它所说,编译器无法弄清楚(我也不能,我想你也不能,因为数据不存在)。
具体问题的解决方案是重载而不是使用默认值:
func addChannel<T>(name: String, data: T?) -> Channel { ... }
func addChannel(name: String) -> Channel { ... }
let myChannel = addChannel("myChannelName")
但它提出了你在这里做什么的问题。你会认为 Channel
应该是 Channel<T>
。否则,你用 data
做什么?如果不求助于 Any
(你应该强烈避免),很难看出你的函数除了忽略 data
.
使用 Channel<T>
您可以只使用默认值,但您必须提供类型:
func addChannel<T>(name: String, data: T? = nil) -> Channel<T> { ... }
let myChannel: Channel<Int> = addChannel("myChannelName")
否则编译器不知道你在制作什么样的频道。
(更新~Swift 5.2)
有时您想要 T
的默认类型。你可以通过重载来做到这一点。例如,您可能希望默认类型为 Never
。在这种情况下,您将添加这样的重载:
func addChannel<T>(name: String, data: T? = nil) -> Channel<T> { ... }
func addChannel(name: String) -> Channel<Never> {
addChannel(name: name, data: Optional<Never>.none)
}
有了它,您可以进行更简单的调用:
let myChannel = addChannel(name: "myChannelName") // Channel<Never>
我运行陷入同样的问题。虽然传统上不能使用通用默认值——完全不考虑参数——但我更喜欢下面的实现重载:
let myChannel=addChannel("myChannelName", data: Optional<Any>.none)
我使用了现有答案的组合,这样我既可以在没有可选参数的情况下调用函数,又可以避免执行函数两次。
func addChannel(name: String) -> Channel {
addChannel(name: name, data: Optional<Any>.nil)
}
func addChannel<T>(name: String, data: T? = nil) -> Channel {
...
}
如上所述,您应该避免 Any
。在我的例子中,我知道 T
是一个 Encodable
所以我使用这个:
struct DefaultEncodable: Encodable {}
func function1(name: String) {
addChannel(name: name, data: Optional<DefaultEncodable>.nil)
}
func function1<T: Encodable>(name: String, data: T? = nil) {
...
}