代码之家  ›  专栏  ›  技术社区  ›  EvGeniy Ilyin

具有associatedtype的Swift协议(类型查找不明确)

  •  6
  • EvGeniy Ilyin  · 技术社区  · 7 年前

    enum : RawRepresentable 哪里 RawValue == String

    protocol RequiresEnum: class {
        associatedtype SectionIdentifierEnum: RawRepresentable // how this add restriction to RawValue == String
    
        func test<T: SectionIdentifierEnum>(identifier: T) where T.RawValue == String
    }
    
    enum RequiresEnumDefault: String {
        case `default`
    }
    
    extension RequiresEnum where Self: UIViewController, SectionIdentifierEnum.RawValue == String {
    
        typealias SectionIdentifierEnum = RequiresEnumDefault
    
        func test<T: SectionIdentifierEnum>(identifier: T) where T.RawValue == String {
            print(T.rawValue)
        }
    
    }
    

    但我有错误

    • “RawValue”不是“T”的成员类型

    有什么解决办法吗

    1 回复  |  直到 7 年前
        1
  •  7
  •   dfrib    7 年前

    一般来说,当在协议的上下文中覆盖泛型时,泛型类型持有者被视为可由 associatedtype 协议的一部分。在您的示例中,这将是 SectionIdentifierEnum ,它充当受约束对象的占位符 SectionIdenfierEnum 但是,它本身不是协议,因此不能将其用作泛型方法中的类型约束。你 可以 但是,请将其用作 test(...)


    Swift 3.1

    现在,目前(Swift 3.1),您不能将复杂的类型约束添加到 关联类型 但是,您可以提供仅适用于以下情况的默认实现: Self 派生自 UIViewController 并实现 RequiresEnum 通过设置 截面标识 RequiresEnumDefault RawValue String 对于此默认实现,作为 原始价值 混凝土的 要求默认值 类型为 一串

    例如。:

    // Swift 3.1
    // ---------
    // Types that implement this protocol mustn't necessarily use a
    // `SectionIdentifierEnum` type where `SectionIdentifierEnum.RawValue` 
    // is constrained to equal `String`. 
    protocol RequiresEnum: class {
        associatedtype SectionIdentifierEnum: RawRepresentable
    
        func test(identifier: SectionIdentifierEnum)
    }
    
    enum RequiresEnumDefault: String {
        case `default`
    }
    
    // This extension, however, is only available for types that use
    // `RequiresEnumDefault ` as the concrete type of `SectionIdentifierEnum`
    // (in which case `SectionIdentifierEnum.RawValue` is `String`).
    extension RequiresEnum where Self: UIViewController, SectionIdentifierEnum == RequiresEnumDefault {
    
        func test(identifier: SectionIdentifierEnum) {
            print(identifier.rawValue)
        }
    }
    
    // Example usage.
    class MyViewController : UIViewController, RequiresEnum {
        typealias SectionIdentifierEnum = RequiresEnumDefault
        // ...
    }
    
    let foo = MyViewController()
    foo.test(identifier: RequiresEnumDefault.default) 
      // prints "default" (using extension:s default implementation)
    

    上面,默认实现 仅在以下情况下可用 截面标识 等于混凝土类型 RequireEnumDefault 自己 派生自 UIViewController 截面标识 一串 已键入 ,则相应地修改扩展的类型约束:

    protocol RequiresEnum: class {
        associatedtype SectionIdentifierEnum: RawRepresentable
    
        func test(identifier: SectionIdentifierEnum)
    }
    
    enum RequiresEnumDefault: String {
        case `default`
    }
    
    extension RequiresEnum where Self: UIViewController, SectionIdentifierEnum.RawValue == String {
    
        func test(identifier: SectionIdentifierEnum) {
            print(identifier.rawValue)
        }
    }
    
    
    // Example usage.
    enum EnumWithStringRawValue: String {
        case foo
    }
    
    class MyViewController : UIViewController, RequiresEnum {
        typealias SectionIdentifierEnum = EnumWithStringRawValue
        // ...
    }
    
    let foo = MyViewController()
    foo.test(identifier: EnumWithStringRawValue.foo)
        // prints "foo" (using extension:s default implementation)
    

    一旦Swift 4发布,您将能够向 :s,根据Swift evolution提案的实施:

    // Swift 4
    // -------
    // Here, all types that implement this protocol must use a
    // `SectionIdentifierEnum` type where `SectionIdentifierEnum.RawValue` 
    // is equal to `String`. 
    protocol RequiresEnum: class {
        associatedtype SectionIdentifierEnum: RawRepresentable 
            where SectionIdentifierEnum.RawValue == String
    
        func test(identifier: SectionIdentifierEnum)
    }
    
    enum RequiresEnumDefault: String {
        case `default`
    }
    
    // For the specific case where `SectionIdentifierEnum` equals
    // `RequiresEnumDefault` (and where `Self` derives from `UIViewController`), 
    // this default implementation is readily available.
    extension RequiresEnum where Self: UIViewController, SectionIdentifierEnum == RequiresEnumDefault {
    
        func test(identifier: SectionIdentifierEnum) {
            print(identifier.rawValue)
        }
    
    }
    
    // Example usage.
    class MyViewController : UIViewController, RequiresEnum {
        typealias SectionIdentifierEnum = RequiresEnumDefault
        // ...
    }
    
    let foo = MyViewController()
    foo.test(identifier: RequiresEnumDefault.default) 
      // prints "default" (using extension:s default implementation)
    

    同样,修改对默认实现的约束 测试(…) 不仅如此 截面标识 等于 要求默认值 (但对于任何枚举:在这种情况下,我们知道此类枚举将始终具有一个 一串 ,由于 关联类型

    protocol RequiresEnum: class {
        associatedtype SectionIdentifierEnum: RawRepresentable 
            where SectionIdentifierEnum.RawValue == String
    
        func test(identifier: SectionIdentifierEnum)
    }
    
    enum RequiresEnumDefault: String {
        case `default`
    }
    
    // From the constraint on the `RawValue` of `SectionIdentifierEnum`
    // above, we know that `RawValue` equals `String`.
    extension RequiresEnum where Self: UIViewController {
    
        func test(identifier: SectionIdentifierEnum) {
            print(identifier.rawValue)
        }
    }
    
    // Example usage.
    enum EnumWithStringRawValue: String {
        case foo
    }
    class MyViewController : UIViewController, RequiresEnum {
        typealias SectionIdentifierEnum = EnumWithStringRawValue
        // ...
    }
    
    let foo = MyViewController()
    foo.test(identifier: EnumWithStringRawValue.foo) 
      // prints "foo" (using extension:s default implementation)