我有一个具有属性的类,该属性应该具有其他语言中称为通用(或模板)接口的类型。当我试图在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方式正确表示这种情况?或者是否有任何已知的解决方法,以便我不必强制或取消推广类结构?
答案 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>) {}
}