【问题标题】:associatedType inside another associatedType using protocols使用协议的另一个关联类型中的关联类型
【发布时间】:2017-05-13 03:49:51
【问题描述】:

对于上述问题,我一直在努力寻找在另一个关联类型中使用泛型和关联类型的解决方案

案例

我想要一个ObjectRequestType,它里面有一个ObjectResponseType类型的关联类型。

protocol ObjectRequestType {
    associatedtype Response: ObjectResponseType
}

另一方面,ObjectResponseType 是具有关联类型 Element 的协议

protocol ObjectResponseType {
    associatedtype Element
}

我想要实现的是我想根据不同类型的元素扩展ObjectRequestType的功能,这里为了举例,我们有两种不同类型的Element

protocol ElementType {}
protocol OtherElementType {}

到目前为止,我将通过以下扩展来实现这一点

extension ObjectRequestType where Response.Element: ElementType {
    static func request() {
        print("ElementType")
    }
}

extension ObjectRequestType where Response.Element: OtherElementType {
    static func request() {
        print("OtherElementType")
    }
}

额外的步骤是处理将此请求传递给我需要使用泛型的类

class DemoClass<Request: ObjectRequestType> {
    static func execute() {
        Request.request()
    }
}

问题

由于在运行中DemoClass 无法定义Response 的类型,Request 会找到它的两个实现,并且会失败并抛出编译错误

错误:对成员“request()”的引用不明确

通过添加额外的where子句来修改类仍然不会这样做,因为我会错过OtherElementType的其余实现

class DemoClass<Request: ObjectRequestType> where Request.Response.Element: ElementType {
    static func execute() {
        Request.request()
    }
}

我一直在尝试解决方法,但我仍然无法实现这种情况。如果有人有任何想法或其他方法,我们会很高兴地欢迎。

【问题讨论】:

  • Request.Response.Element: ElementType
  • @Kevin 谢谢,这是一个错字,但还是看看我的问题是什么
  • 有任何理由 static func request() 不是 ObjectRequestType 协议的一部分吗?
  • @Kevin 这是让static func request() 根据关联类型提供不同实现的主要思想
  • 嗯,是的,这就是协议扩展的作用。如果它不是协议的一部分,则无法保证在实现ObjectRequestType 的任何特定实体上甚至存在request 函数。你可以在运行时检查类型,但这种风格很糟糕而且容易出错。

标签: swift generics


【解决方案1】:

执行此操作的通常方法是将request 方法添加到ObjectResponseType 协议中,这样您就可以保证它存在于任何符合要求的类型上。然后,您创建一个协议扩展,为您知道如何处理的类型提供默认实现,您已经完成了。如果您需要使用现有元素类型之一覆盖某个请求的请求,您可以这样做。如果您需要支持其他元素类型,您可以直接在请求中完成,也可以添加其他协议扩展。

protocol ObjectResponseType {
    associatedtype Element
}
protocol ObjectRequestType {
    associatedtype Response: ObjectResponseType

    static func request()
}

protocol ElementType {}

extension ObjectRequestType where Response.Element: ElementType {
    static func request() {
        print("ElementType")
    }
}
protocol OtherElementType {}
extension ObjectRequestType where Response.Element: OtherElementType {
    static func request() {
        print("OtherElementType")
    }
}

class DemoClass<Request: ObjectRequestType> {
    static func execute() {
        Request.request()
    }
}

class Foo: ElementType {}
class FooResponse: ObjectResponseType {
    typealias Element = Foo
}
class FooRequest: ObjectRequestType {
    typealias Response = FooResponse
}

class Bar: OtherElementType {}
class BarResponse: ObjectResponseType {
    typealias Element = Bar
}
class BarRequest: ObjectRequestType {
    typealias Response = BarResponse
    // Override the default implementation
    static func request() {
        print("Bar")
    }
}

class Baz {}
class BazResponse: ObjectResponseType {
    typealias Element = Baz
}
class BazRequest: ObjectRequestType {
    typealias Response = BazResponse

    static func request() {
        print("Baz")
    }
}

DemoClass<FooRequest>.execute() // ElementType
DemoClass<BarRequest>.execute() // Bar
DemoClass<BazRequest>.execute() // Baz

【讨论】:

    猜你喜欢
    • 2020-11-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多