是否有必要将类型参数传递给泛型 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

我想出了两个解决方法:

  1. GenericClass 一个类型参数——无论哪种类型:

    let y: Int = GenericClass<Void>.blub(4)
    
  2. 创建第二个 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是什么,它可以是任何东西”,这就是我们想要的。