作为泛型类型的默认参数
Default parameter as generic type
我有协议和他的实现写在Swift:
protocol P {
}
struct A: P {
}
协议被用作某些函数的通用类型:
func foo<T: P>(param: T) {
}
func foo() {
foo(param: A())
}
到目前为止一切正常。但我想将 A() 设置为给定函数的默认参数:
func foo<T: P>(param: T = A()) {
}
不幸的是,出现以下错误:
Default argument value of type 'A' cannot be converted to type 'T'.
或
func foo<T: P>(param: T = A() as P) {
}
,
let a: P = A()
func foo<T: P>(param: T = a) {
}
Returns:
Default argument value of type 'P' cannot be converted to type 'T'
或
func foo<T: P>(param: T = A() as T) {
}
Returns:
'A' is not convertible to 'T'; did you mean to use 'as!' to force downcast?
我做错了什么?问题出在哪里?
我不想像这样使用强制转换:
func foo<T: P>(param: T = A() as! T) {
}
提前致谢。
您正试图在泛型函数中强制执行非泛型默认参数:您可能应该考虑一下您要在此处实现的目标。
为了便于讨论,您 可以 在您的函数签名中包括尝试将 A()
转换为 T
,但您需要将参数类型更改为可选以允许失败的转换 (nil
),例如
func foo<T: P>(param: T? = (A() as? T)) { }
一个更合理的选择是——除了你的泛型函数——一个具体的非泛型函数,用于 T
是 A
的实例(具体函数将优先于泛型函数),在这种情况下,您可以在具体函数的函数签名中包含 A()
的默认参数。例如
protocol P { }
struct A: P { }
extension Int: P { }
func foo<T: P>(param: T) { print("called generic foo") }
func foo(param: A = A()) { print("called A specific foo") }
foo() // called A specific foo (making use of default arg)
foo(A()) // called A specific foo
foo(1) // called generic foo
请注意,即使 A
符合 P
,也会调用非泛型 foo
(A
可能 使用了泛型 foo
):这里没有冲突,因为具体函数优先。
另一方面,如果您只希望通用函数允许在没有单个参数的情况下进行调用(即,使用默认参数),则可以在 [=20= 中包含一个简单初始化程序的蓝图],允许您将泛型类型的实例初始化为默认参数;参见 。
您唯一需要做的就是在协议中添加对初始化程序的要求:
protocol P {
init()
}
struct A: P {
var x: Int
init() {
x = 10
}
}
func foo<T: P>(param param: T = T()) {
}
但是,您会遇到另一个问题。传递的参数的类型决定泛型的类型,因此您必须以其他方式指定泛型类型。
我有协议和他的实现写在Swift:
protocol P {
}
struct A: P {
}
协议被用作某些函数的通用类型:
func foo<T: P>(param: T) {
}
func foo() {
foo(param: A())
}
到目前为止一切正常。但我想将 A() 设置为给定函数的默认参数:
func foo<T: P>(param: T = A()) {
}
不幸的是,出现以下错误:
Default argument value of type 'A' cannot be converted to type 'T'.
或
func foo<T: P>(param: T = A() as P) {
}
,
let a: P = A()
func foo<T: P>(param: T = a) {
}
Returns:
Default argument value of type 'P' cannot be converted to type 'T'
或
func foo<T: P>(param: T = A() as T) {
}
Returns:
'A' is not convertible to 'T'; did you mean to use 'as!' to force downcast?
我做错了什么?问题出在哪里?
我不想像这样使用强制转换:
func foo<T: P>(param: T = A() as! T) {
}
提前致谢。
您正试图在泛型函数中强制执行非泛型默认参数:您可能应该考虑一下您要在此处实现的目标。
为了便于讨论,您 可以 在您的函数签名中包括尝试将 A()
转换为 T
,但您需要将参数类型更改为可选以允许失败的转换 (nil
),例如
func foo<T: P>(param: T? = (A() as? T)) { }
一个更合理的选择是——除了你的泛型函数——一个具体的非泛型函数,用于 T
是 A
的实例(具体函数将优先于泛型函数),在这种情况下,您可以在具体函数的函数签名中包含 A()
的默认参数。例如
protocol P { }
struct A: P { }
extension Int: P { }
func foo<T: P>(param: T) { print("called generic foo") }
func foo(param: A = A()) { print("called A specific foo") }
foo() // called A specific foo (making use of default arg)
foo(A()) // called A specific foo
foo(1) // called generic foo
请注意,即使 A
符合 P
,也会调用非泛型 foo
(A
可能 使用了泛型 foo
):这里没有冲突,因为具体函数优先。
另一方面,如果您只希望通用函数允许在没有单个参数的情况下进行调用(即,使用默认参数),则可以在 [=20= 中包含一个简单初始化程序的蓝图],允许您将泛型类型的实例初始化为默认参数;参见
您唯一需要做的就是在协议中添加对初始化程序的要求:
protocol P {
init()
}
struct A: P {
var x: Int
init() {
x = 10
}
}
func foo<T: P>(param param: T = T()) {
}
但是,您会遇到另一个问题。传递的参数的类型决定泛型的类型,因此您必须以其他方式指定泛型类型。