是否有必要将类型参数传递给泛型 class 中的静态函数?
Is it necessary to pass a type parameter to static functions in a generic class?
My class: my class 采用一个类型参数,并且有一个不使用类型参数的静态方法:
class GenericClass<T> {
static func blub(x: Int) -> Int {
return x + 1
}
}
我的问题: 当我尝试使用静态函数时,我的代码无法编译:
let z: Int = GenericClass.blub(4) // doesn't compile
我想出了两个解决方法:
给 GenericClass
一个类型参数——无论哪种类型:
let y: Int = GenericClass<Void>.blub(4)
创建第二个 class,它没有任何类型参数,用于保存静态方法
所以我知道如何让代码正常工作,尽管它可能不是最佳解决方案。但我的问题是为什么 Swift 以这种方式工作。
我的问题:
为什么 let y: Int = GenericClass.blub(4)
无法编译?
它应该编译,因为 blub
是一个静态方法,因此不应该与类型参数有任何交互,这些参数只用于 实例 ,不用于静态方法和变量。或者至少,这是我所期望的。
我哪里错了? class级类型参数和静态方法如何在Swift中交互?
有没有比我试过的两种解决方法更好的方法来解决这个问题?
截图:
事实上,您可以从静态方法中引用泛型类型参数。例如:
struct Wrapper<T> {
var value: T
private init(_ value: T) {
self.value = value
}
static func wrap(_ value: T) -> Self {
return Self(value)
}
}
在这种情况下可以推断通用参数:
let wrapped = Wrapper.wrap(3) // => Wrapper<Int>
GenericClass
不是 Swift 中的具体类型。没有办法谈论它,就像你不能在不提供其类型参数的情况下谈论类型 Array
一样。 (Swift 缺少的特定功能将被称为 "higher-kinded types.")
静态方法绑定到具体类型 (GenericClass<T>
),而不绑定到更高级的类型 (GenericClass
)。为了访问静态方法,它需要知道您想要的实际类型。
虽然您目前确实没有在此 class 方法中使用类型参数,但没有什么可以阻止您(或子class!)这样做。由于您无法保证 T
永远不会在此方法中出现,因此 Swift 也无法让您忽略它。
其他答案在他们的解释中是正确的,但实际上您可以通过以下方式获得您直观预期的行为:
extension GenericClass where T == Any {
static func blub(x: Int) -> Int {
return x + 1
}
}
现在编译:
let z: Int = GenericClass.blub(x: 4)
注意:Any
有时被视为代码味道。也就是说,它是这里的正确工具。这里的where T == Any
守卫可以解释为“对于这个静态函数,我不关心T是什么,它可以是任何东西”,这就是我们想要的。
My class: my class 采用一个类型参数,并且有一个不使用类型参数的静态方法:
class GenericClass<T> {
static func blub(x: Int) -> Int {
return x + 1
}
}
我的问题: 当我尝试使用静态函数时,我的代码无法编译:
let z: Int = GenericClass.blub(4) // doesn't compile
我想出了两个解决方法:
给
GenericClass
一个类型参数——无论哪种类型:let y: Int = GenericClass<Void>.blub(4)
创建第二个 class,它没有任何类型参数,用于保存静态方法
所以我知道如何让代码正常工作,尽管它可能不是最佳解决方案。但我的问题是为什么 Swift 以这种方式工作。
我的问题:
为什么 let y: Int = GenericClass.blub(4)
无法编译?
它应该编译,因为 blub
是一个静态方法,因此不应该与类型参数有任何交互,这些参数只用于 实例 ,不用于静态方法和变量。或者至少,这是我所期望的。
我哪里错了? class级类型参数和静态方法如何在Swift中交互?
有没有比我试过的两种解决方法更好的方法来解决这个问题?
截图:
事实上,您可以从静态方法中引用泛型类型参数。例如:
struct Wrapper<T> {
var value: T
private init(_ value: T) {
self.value = value
}
static func wrap(_ value: T) -> Self {
return Self(value)
}
}
在这种情况下可以推断通用参数:
let wrapped = Wrapper.wrap(3) // => Wrapper<Int>
GenericClass
不是 Swift 中的具体类型。没有办法谈论它,就像你不能在不提供其类型参数的情况下谈论类型 Array
一样。 (Swift 缺少的特定功能将被称为 "higher-kinded types.")
静态方法绑定到具体类型 (GenericClass<T>
),而不绑定到更高级的类型 (GenericClass
)。为了访问静态方法,它需要知道您想要的实际类型。
虽然您目前确实没有在此 class 方法中使用类型参数,但没有什么可以阻止您(或子class!)这样做。由于您无法保证 T
永远不会在此方法中出现,因此 Swift 也无法让您忽略它。
其他答案在他们的解释中是正确的,但实际上您可以通过以下方式获得您直观预期的行为:
extension GenericClass where T == Any {
static func blub(x: Int) -> Int {
return x + 1
}
}
现在编译:
let z: Int = GenericClass.blub(x: 4)
注意:Any
有时被视为代码味道。也就是说,它是这里的正确工具。这里的where T == Any
守卫可以解释为“对于这个静态函数,我不关心T是什么,它可以是任何东西”,这就是我们想要的。