具有关联类型的Swift协议 - 类型可能不会将自身引用为要求

时间:2022-03-18 11:14:27

I have the following protocol and its extension

我有以下协议及其扩展

public protocol RESEndpointReachable: CustomDebugStringConvertible
{
    associatedtype EndpointType: RESEndpointReachable


    //  MARK: - Properties

    /// The name of the endpoint as defined in the REST URI.
    var name: String { get }

    /// An array of possible next endpoints that this endpoint can reach. E.g account's next endpoints would be authenticate and unauthenticate.
    var nextPossibleEndpoints: [EndpointType] { get }


    //  MARK: - Ability

    /// Used to process the endpoint.
    func processRequest(request: RERequest)

    /// Processes the next endpoint that matches the name `name`. Expects an endpoint with the name `name` to exist in `nextPossibleEndpoints`.
    func processNextEndpointWithName(name: String, request: RERequest)
}

public extension RESEndpointReachable
{
    //  MARK: - CustomDebugStringConvertible

    public var debugDescription: String {
        return name
    }


    //  MARK: - RESEndpointReachable

    var nextPossibleEndpoints: [EndpointType] {
        return []
    }

    public func processRequest(request: RERequest)
    {
        //  Check all possible endpoints are being processed
        if let nextEndpoint = nextPossibleEndpoints.first
        {
            fatalError("Unhandled endpoint \(nextEndpoint).")
        }
    }

    public func processNextEndpointWithName(name: String, request: RERequest)
    {
        //  Get the next endpoint that matches the specified name
        let nextEndpoints = nextPossibleEndpoints.filter { $0.name == name }

        if nextEndpoints.count > 1
        {
            fatalError("Multiple next endpoints found with the name '\(name)'.")
        }

        guard let nextEndpoint = nextEndpoints.first else
        {
            fatalError("No next endpoint with the name '\(name)'.")
        }


        //  Process the next endpoint
        nextEndpoint.processRequest(request)
    }
}

On building, the line associatedtype EndpointType: RESEndpointReachable has the following error: Type may not reference itself as a requirement. But as I understand it this is how you use associated types in Swift.

在构建时,相关联的行类型EndpointType:RESEndpointReachable具有以下错误:类型可能不会将自身引用为要求。但据我所知,这是你在Swift中使用相关类型的方式。

As you may have guessed, I always want whatever EndpointType ends up being set as to be a type that inherits from RESEndpointReachable.

正如您可能已经猜到的那样,我总是希望将EndpointType最终设置为继承自RESEndpointReachable的类型。

2 个解决方案

#1


4  

This feature is referred to by the Swift team as 'recursive protocol constraints', and is on the roadmap to be added in a future version of Swift. For more information about this and other planned features, check out the Swift team's 'Completing Generics' manifesto.

Swift团队将此功能称为“递归协议约束”,并在未来版本的Swift中添加路线图。有关此计划功能和其他计划功能的更多信息,请查看Swift团队的“完成泛型”宣言。

#2


1  

Yep, that is not OK with swift. A protocol can't use it self as a type constraint. One solution is to declare an extra protocol that RESEndpointReachable itself will adopt and constraint RESEndpointReachable to that super protocol.

是的,这对swift来说不行。协议不能将其自身用作类型约束。一种解决方案是声明RESEndpointReachable本身将采用的额外协议,并将RESEndpointReachable约束到该超级协议。

I took the example from the book iOS 10 Programming Fundamentals with Swift by Neuburg M. (please see page 194)

我从Neuburg M.的“iOS 10编程基础与Swift”一书中获取了这个例子(请参阅第194页)

illegal example:

  1 protocol Flier {
  2         associatedtype Other : Flier
  3         func flockTogetherWith(_ f: Other)
  4 }
  5 
  6 struct Bird : Flier {
  7         func flockTogetherWith(_ f: Bird) {}
  8 }

Solution:

  1 protocol Superflier {}
  2 protocol Flier: Superflier {
  3         associatedtype Other : Superflier
  4         func flockTogetherWith(_ f: Other)
  5 }       
  6 
  7 struct Bird : Flier {
  8         func flockTogetherWith(_ f: Bird) {}
  9 } 

Cheers

#1


4  

This feature is referred to by the Swift team as 'recursive protocol constraints', and is on the roadmap to be added in a future version of Swift. For more information about this and other planned features, check out the Swift team's 'Completing Generics' manifesto.

Swift团队将此功能称为“递归协议约束”,并在未来版本的Swift中添加路线图。有关此计划功能和其他计划功能的更多信息,请查看Swift团队的“完成泛型”宣言。

#2


1  

Yep, that is not OK with swift. A protocol can't use it self as a type constraint. One solution is to declare an extra protocol that RESEndpointReachable itself will adopt and constraint RESEndpointReachable to that super protocol.

是的,这对swift来说不行。协议不能将其自身用作类型约束。一种解决方案是声明RESEndpointReachable本身将采用的额外协议,并将RESEndpointReachable约束到该超级协议。

I took the example from the book iOS 10 Programming Fundamentals with Swift by Neuburg M. (please see page 194)

我从Neuburg M.的“iOS 10编程基础与Swift”一书中获取了这个例子(请参阅第194页)

illegal example:

  1 protocol Flier {
  2         associatedtype Other : Flier
  3         func flockTogetherWith(_ f: Other)
  4 }
  5 
  6 struct Bird : Flier {
  7         func flockTogetherWith(_ f: Bird) {}
  8 }

Solution:

  1 protocol Superflier {}
  2 protocol Flier: Superflier {
  3         associatedtype Other : Superflier
  4         func flockTogetherWith(_ f: Other)
  5 }       
  6 
  7 struct Bird : Flier {
  8         func flockTogetherWith(_ f: Bird) {}
  9 } 

Cheers