Swift中通用类型的工厂(协议和泛型)

时间:2015-07-29 20:03:07

标签: ios swift generics

我正在尝试创建一个实现协议的泛型类型的工厂。问题是,在适配器工厂的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
    }
}

1 个答案:

答案 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#一样简化。

希望这有帮助。