我有这段代码:
protocol GenericProtocol: class {
associatedtype type
func funca(component: type)
}
class MyType<T> {
weak var delegate: GenericProtocol? // First error
var t: T
init(t: T) {
self.t = t
}
func finished() {
delegate?.funca(component: t) // Second error
}
}
class UsingGenericProtocol: GenericProtocol {
let myType: MyType<Int>
typealias type = Int
init() {
myType = MyType<Int>(t: 0)
}
func funca(component: Int) {
}
}
我想使用给定类型的委托。代码将无法编译,因为我收到了这个错误:
协议'GenericProtocol'只能用作通用约束 因为它有自我或相关的类型要求
和
会员'funca'不能用于协议类型的值 'GenericProtocol';使用通用约束
我可以通过从协议中删除类型,将其设置为Any然后将其转换为正确的类型来省略此错误,但我认为泛型应该涵盖此问题。有什么方法可以让这个代码编译?感谢。
答案 0 :(得分:3)
泛型和相关类型之间的区别在于,在实例化时指定泛型,在实现期间指定相关类型。因此,您不能将协议类型用作具体类型,因为关联类型取决于实现类型。
但是,有一些解决方法:
1)使用委托的类型作为泛型类型:
class MyType<Delegate: GenericProtocol> {
typealias T = Delegate.type
...
}
2)在委托方法中使用通用协议而不是关联类型:
protocol CommonProtocol { ... }
protocol DelegateProtocol {
func funca(component: CommonProtocol)
}
3)使用闭包进行类型擦除(这也是在Sequence
协议的AnySequence<Element>
协议的Swift标准库中完成的)
struct AnyGenericProtocol<GenericType>: GenericProtocol {
typealias type = GenericType
private let f: (GenericType) -> ()
init<G: GenericProtocol>(_ g: GenericProtocol) where G.type == GenericType {
f = { component in
g.funca(component: component)
}
}
func funca(component: GenericType) {
f(component)
}
}
class MyType<T> {
var delegate: AnyGenericProtocol<T>
...
}
答案 1 :(得分:2)
这不可能使用通用协议。请改用具体类型或通用协议。你必须在那些抽象之外声明具体的T
例如,这应该有效:
class MyType<T> {
weak var delegate: UsingGenericProtocol<T>? // First error
var t: T
init(t: T) {
self.t = t
}
func finished() {
delegate?.funca(component: t) // Second error
}
}
class UsingGenericProtocol<T>: GenericProtocol {
let myType: MyType<T>
typealias type = T
init(t: T) {
myType = MyType<T>(t: t)
}
func funca(component: T) {
}
}
let instance = UsingGenericProtocol<Int>(t: 0)