加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

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

发布时间:2020-12-14 04:40:35 所属栏目:百科 来源:网络整理
导读:我需要在协议中创建泛型函数,并在扩展中使用默认实现.它应该使用item作为枚举:RawRepresentable,其中RawValue == String always.我试过了 protocol RequiresEnum: class { associatedtype SectionIdentifierEnum: RawRepresentable // how this add restric
我需要在协议中创建泛型函数,并在扩展中使用默认实现.它应该使用item作为枚举:RawRepresentable,其中RawValue == String always.我试过了

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)
    }

}

但我有错误

  • ‘SectionIdentifierEnum’ is ambiguous for type lookup in this context
  • ‘RawValue’ is not a member type of ‘T’

任何解决方案

解决方法

通常,当在协议的上下文中覆盖泛型时,通用类型持有者被视为可由协议的相关类型表示.在您的示例中,这将是SectionIdentifierEnum,它充当受约束类型的占位符.但是,SectionIdenfierEnum本身不是一个协议,因此不能将它用作泛型方法中的类型约束.但是,您可以在test(…)方法中将其用作类型本身.

Swift 3.1

现在,当前(Swift 3.1),您无法将复杂的类型约束添加到关联类型.但是,您可以提供一个默认实现,仅适用于Self从UIViewController派生的情况,并通过将SectionIdentifierEnum类型设置为具体的RequiresEnumDefault类型来实现RequiresEnum协议.后者将确定关联的RawValue是此默认实现的String,因为具体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)

上面,test(…)的默认实现仅在SectionIdentifierEnum等于具体类型RequireEnumDefault(和Self派生自UIViewController …)时可用.如果您希望它仅在SectionIdentifierEnum是具有String类型RawValue的任何枚举时可用,则相应地修改扩展的类型约束:

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发布,您将能够根据Swift evolution提案的实现向关联类型添加更复杂的约束:

> SE-0142: Permit where clauses to constrain associated types

在这种情况下,上述内容可以修改为:

// 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)

同样修改对test(…)的默认实现的约束,不仅仅是对于SectionIdentifierEnum等于RequiresEnumDefault的情况(但对于任何枚举:在这种情况下,我们知道这样的枚举将始终具有RawValue字符串,因为对协议定义中的associatedtype).

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)

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读