关于模板:在Apple的Swift中实现通用接口

Implementing generic interfaces in Apple's Swift

我有一个带有属性的类,该类的类型应为其他语言中的通用(或模板)接口。 当我尝试在Swift中模仿这种行为时,我无法获得适用于该想法的协议。 例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
protocol P {
    typealias T
    func returnT() -> T
}

class G< T >: P {
    var t: T

    init(t: T) {
        self.t = t
    }

    func returnT() -> T {
        return t
    }
}

class C {
    var p: P<Int>               // Cannot specialize non-generic type 'P'

    init(instanceOfP: P<Int>) { // Cannot specialize non-generic type 'P'
        p = instanceOfP
    }

    func usePsT() -> Int {
        return p.returnT()      // 'P' does not have a member named  'returnT'
    }
}

来自编译器的错误报告为注释。 在我看来,这种情况应该不会有问题:但是,由于Swift的协议不能是泛型的(它们使用了晦涩的typealias语法),因此C无法知道实现P的每个类都可以 专用于Int。 有一种Swift-y方法可以正确表示这种情况吗? 还是有任何已知的解决方法,使我不必强制或取消泛化类结构?


协议中实际上并不需要泛型(使用Any),而class G< T >中则需要泛型。 你可以做...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
protocol P {
    func returnT() -> Any
}

class G< T >: P {
    var t: T

    init(t: T) {
        self.t = t
    }

    func returnT() -> Any {
        return t
    }
}

class C {
    var p: P

    init(instanceOfP: P) {
        p = instanceOfP
    }

    func usePsT() -> Any {
        return p.returnT()
    }
}

let gi = G<Int>(t: 7) // {t 7}
let ci = C(instanceOfP: gi) // {{t 7}}
ci.usePsT() // 7

let gs = G<String>(t:"Hello")
let cs = C(instanceOfP: gs)
cs.usePsT() //"Hello"


我的解决方案不是很理想,但是却省了很多麻烦,但代码仍然可读...
我使用开放空函数的基类代替接口。
像这样:

1
2
3
4
5
public class CSTableControllerFilter<Row: CSTableControllerRow, Data> {
    open func filter(data: [Row]) -> [Row] { data }

    open func onReloadDone(in controller: CSTableController<Row, Data>) {}
}