如何在Swift中向泛型类型添加类型方法?

时间:2015-04-17 13:44:01

标签: ios swift generics

我正在尝试向Swift中的泛型类添加一个类型(aka静态)方法。这是代码。

class StateArchive<T> {
    class func emptyAllArchives() {
        // do something
    }
}

// the compiler emits an error: "Argument for generic parameter 'T' could not be inferred"
StateArchive.emptyAllArchives()

我可以通过提供代替T的类型来编译上面的代码:

StateArchive<AnyObject>.emptyAllArchives()

然而,这看起来很尴尬。最初我认为这可能是因为可以创建一个类型为T的类变量。在操场上的快速测试显示编译器发出一条消息说:

“泛型类型尚不支持的类存储属性”。

有没有人知道如何在泛型类型中创建一个类型方法,让客户端调用此方法而不提供代替T的类型?

2 个答案:

答案 0 :(得分:7)

当遇到泛型无法正常工作的问题时,为了帮助理解这个问题,通常会有用,想一想如果用不同的具体类型替换占位符会发生什么。

例如,假设你定义了以下内容(由于你给出的原因,这不会编译,但想象一下):

class C<T> {
    static var a: [T] = []

    static func addElement(i: T) {
        a.append(i)
    }
}

真的,当你写class C<T>时,你不是在写一堂课。您正在为无数可能的类编写蓝图 - C<Int>C<String>C<AnythingElse>

在这种情况下,假设您撰写了C.addElement(1) - 所以T将是Int。然后,你写了C.addElement("one")C.a现在会包含一个项目,还是两个? a的类型是什么?

可能最合理的答案是,C<Int>.a有一个元素,C<String>.a有一个元素。但这可能会让人感到非常困惑,并且似乎没有用例来证明这种功能的合理性。

通常,静态方法和属性最好很少使用,并且您可能会发现使用非静态成员和方法,结合单例模式(或者甚至可能不是这样)会更好。如果您仍然需要类似静态的函数,那么最好使用通用的自由函数(例如func emptyArchive<T: C>(c: C) { })。

答案 1 :(得分:0)

另一个答案在其解释中是正确的,但实际上您可以通过以下方式获得您直觉上期望的行为:

extension StateArchive where T == Any {

    static func emptyAllArchives() {
        // do something
    }
}

// works as expected
StateArchive.emptyAllArchives()