2016-05-16 10 views
5

Mam następujący protokół i jego rozszerzenieSwift protokół z wiązanego typu - typ nie może odwoływać się jako wymóg

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

Na budynku, linia associatedtype EndpointType: RESEndpointReachable ma następujący błąd: Type may not reference itself as a requirement. Ale jak rozumiem, w ten sposób używasz powiązanych typów w Swift.

Jak można się domyślić, zawsze chcę, aby to, co EndpointType, zostało ustawione jako typ dziedziczący po RESEndpointReachable.

+0

Nie mam tej funkcji Ble teraz! Ref: https://gist.github.com/curtclifton/1923a47774a94e904bf0 https://forums.developer.apple.com/thread/15256. To sprawi, że kompilator będzie działał w pętlach rekursywnych – sargeras

+0

Dzięki :) Pomyślałem, że może być tak ... Może w przyszłym miesiącu ... –

Odpowiedz

3

Ta funkcja jest określana przez zespół Swift jako "ograniczenia protokołu rekursywnego" i znajduje się na mapie drogowej, którą należy dodać w przyszłej wersji Swift. Aby uzyskać więcej informacji na temat tej i innych planowanych funkcji, zapoznaj się z 'Completing Generics' manifesto zespołu Swift.

+0

Wydaje mi się niedorzeczne, że Swift 4 nadal nie obsługuje tego -.- – d4Rk

+0

Według komentarza Douga Gregora w śledzeniu problemu (https://bugs.swift.org/browse/SR-1445), zostało ono wydane wraz z Swift 4.1, więc najnowszy Xcode _should_ powinien być dostarczany z kompilatorem, który go obsługuje. (Nie próbowałem tego sam, więc nie wiem, jak dobrze funkcja działa w praktyce ...) – AustinZ

1

Tak, to nie jest w porządku z szybkim. Protokół nie może używać go jako ograniczenia typu. Jednym z rozwiązań jest zadeklarowanie dodatkowego protokołu, który sam przyjmie RESEndpointReachable i ograniczy RESEndpointReachable do tego super protokołu.

Wziąłem przykład z książki iOS 10 Podstawy programowania z Swift przez Neuburg M. (patrz strona 194)

nielegalne przykład:

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

Rozwiązanie:

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 } 

Pozdrowienia

Powiązane problemy