我正在尝试创建一个实现协议的泛型类型的工厂。问题是,在适配器工厂的make
方法中,我收到以下错误:Protocol 'Adapter' can only be used as a generic constraint because it has Self or associated type requirements
。
以下是我现在正在做的一个例子:
protocol Adapter {
typealias T
static func method1(parameter: T)
}
final class AdapterFactory<T>: NSObject {
static func make(name: String = "") -> Adapter.Type {
switch name {
case "Adapter1":
return ConcreteAdapter1<T>.self
default:
return ConcreteAdapter2<T>.self
}
}
}
final class ConcreteAdapter1<T>: NSObject, Adapter {
static func method1(parameter: T) {
// bla, bla, bla
}
}
答案 0 :(得分:3)
您可以使用swift标准库中使用的模式(请参阅Sequence和AnySequence),即使用AnyAdapter实现Adapter协议,通过将每个方法调用委托给底层实现(适配器协议的具体实现,如ConcreteAdapter1)或者使用闭包。
然后您的工厂将返回AnyAdapter而不是Adapter。起初看起来似乎不自然,但是使用AnyAdapter作为类型提供了与使用协议相同的优势(显然它是一种解决方法),因为AnyAdapter本身并不是具体实现,而是将实现委托给具体实现。
这是代码
protocol Adapter {
typealias Element
func method1(parameter: Element)
func method2(parameter : Element)
}
struct AnyAdapter<Element> : Adapter {
private let _method1 : (Element) -> ()
private let _method2 : (Element) -> ()
init<A:Adapter where A.Element == Element>(_ base:A) {
_method1 = { base.method1($0) }
_method2 = { base.method2($0) }
}
func method1(parameter: Element) {
_method1(parameter)
}
func method2(parameter: Element) {
_method2(parameter)
}
}
final class ConcreteAdapter1<T>: NSObject, Adapter {
func method1(parameter: T) {
print("Concrete Adapter 1 method 1")
}
func method2(parameter: T) {
print("Concrete Adapter 1 method 2")
}
}
final class ConcreteAdapter2<T> : Adapter {
func method1(parameter: T) {
print("Concrete adapter 2 method 1")
}
func method2(parameter: T) {
print("Concrete Adapter 2 method 2")
}
}
final class AdapterFactory<T>: NSObject {
static func make(name: String = "") -> AnyAdapter<String> {
switch name {
case "Adapter1":
let concreteAdapter1 = ConcreteAdapter1<String>()
return AnyAdapter(concreteAdapter1)
default:
let concreteAdapter2 = ConcreteAdapter2<String>()
return AnyAdapter(concreteAdapter2)
}
}
}
我没有在协议中使用静态方法来使事情变得更简单,因为静态不适用于泛型类型。
说实话,这是语言的一个缺点,我希望它像java或C#一样简化。
希望这有帮助。