继承通用协议

时间:2017-03-22 02:36:17

标签: swift swift-protocols

我有2个从一个通用协议继承的协议

protocol IdentifierProtocol: Equatable, RawRepresentable {}

protocol A_IdentifierProtocol: IdentifierProtocol {}
protocol B_IdentifierProtocol: IdentifierProtocol {}

我希望使用函数进行拆分,但此代码会出错

extension UIClass {
    func myFunc<I: IdentifierProtocol>(identifier: I) where I.RawValue == String {
         if identifier is A_IdentifierProtocol { // <- Error
             print("A")
         }
         if identifier is B_IdentifierProtocol { // <- Error
             print("B")
         }
    }
}
  

错误:协议&#39; A_IdentifierProtocol&#39;只能用作通用约束,因为它具有Self或关联类型要求

我该如何解决这个问题?

1 个答案:

答案 0 :(得分:0)

IdentifierProtocolRawRepresentableassociatedType。并且这样的协议不能使用&#34;就好像它是具体的类型&#34;。

这基本上就是编译错误所说的:

  

错误:协议&#39; A_IdentifierProtocol&#39;只能用作通用约束,因为它具有Self或关联类型要求

我建议您阅读有关错误的解释,而不是复制信息:https://stackoverflow.com/a/36350283/2378431

如果你想解决这个错误并仍然让代码工作没有任何明显的区别(从使用角度来看),你可以为每个X_IdentifierProtocol定义单个方法,如下所示:

protocol IdentifierProtocol: Equatable, RawRepresentable {}

protocol A_IdentifierProtocol: IdentifierProtocol {}
protocol B_IdentifierProtocol: IdentifierProtocol {}

func myFunc<I: A_IdentifierProtocol>(identifier: I) where I.RawValue == String {
    print("A: \(identifier.rawValue)")
}

func myFunc<I: B_IdentifierProtocol>(identifier: I) where I.RawValue == String {
    print("B: \(identifier.rawValue)")
}

缺点是,对于每个X_IdentifierProtocol,您需要提供一个方法实现,并且如果您希望基于IdentifierProtocol拥有一段共享代码,则可能会引入一些代码重复。

另一种方法:如果您真的想要单一功能,则不能将IdentifierProtocol与关联类型相关联。但是,您可以对泛型函数有多种类型约束,如下所示:

protocol IdentifierProtocol {}

protocol A_IdentifierProtocol: IdentifierProtocol {}
protocol B_IdentifierProtocol: IdentifierProtocol {}

func myFunc<I: IdentifierProtocol & Equatable & RawRepresentable>(identifier: I) where I.RawValue == String {
    if identifier is A_IdentifierProtocol {
        print("A: \(identifier.rawValue)")
    }
    if identifier is B_IdentifierProtocol {
        print("A: \(identifier.rawValue)")
    }
}

class MyClassA: A_IdentifierProtocol, RawRepresentable, Equatable {...}
class MyClassB: B_IdentifierProtocol, RawRepresentable, Equatable {...}

但即使这样也不完美,也不能完全满足您的要求。

底线是你无法用Swift 3完全达到你想要的效果。