在Apple的Swift

时间:2015-04-25 15:33:49

标签: swift templates generics interface protocols

我有一个具有属性的类,该属性应该具有其他语言中称为通用(或模板)接口的类型。当我试图在Swift中模仿这种行为时,我无法让协议与这个想法一起工作。例如:

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方式正确表示这种情况?或者是否有任何已知的解决方法,以便我不必强制或取消推广类结构?

2 个答案:

答案 0 :(得分:1)

您的协议中真正需要通用(使用Any) - class G<T>中需要它。你可以这样做......

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 :(得分:0)

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

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

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