2 votes

Comment déclarer des méthodes qui renvoient une séquence de Structs personnalisés en Swift ?

Quelle est la bonne façon de déclarer une fonction qui renvoie une séquence en Swift 4. J'ai essayé ce qui suit mais j'ai reçu une erreur disant :

erreur : Models.playground:29:13 : error : cannot convert return expression of type 'Cars' to return type 'S' (erreur : ne peut pas convertir l'expression de retour de type 'Cars' en type de retour 'S') return Cars(cars) ^~~~~~ as ! S

Voici le code que j'ai utilisé :

import Foundation

struct Car {
    let make:String
    let model:String
}

class Cars: Sequence, IteratorProtocol {
    typealias Element = Car

    var current = 0
    let cars:[Element]
    init(_ cars:[Element]) {
        self.cars = cars;
    }

    func makeIterator() -> Iterator {
        current = 0
        return self
    }

    func next() -> Element? {
        if current < cars.count {
            defer { current += 1 }
            return cars[current]
        } else {
            return nil
        }
    }
}

let cars = Cars([Car(make:"Buick", model:"Century"), Car(make:"Buick", model:"LaSabre")])

func getCars<S:Sequence>(cars:[Car]) -> S where S.Iterator.Element == Car {
    return  Cars(cars)
}

3voto

Martin R Points 105727

La valeur de retour ne peut pas être une spécialisation de la fonction Sequence protocole. Vous pouvez soit retourner Cars lui-même, comme Daniel a suggéré ou - si vous voulez cacher l'implémentation de la séquence - une séquence "effacée" :

func getCars(cars:[Car]) -> AnySequence<Car> {
    return AnySequence(Cars(cars))
}

ou même

func getCars(cars:[Car]) -> AnySequence<Car> {
    return AnySequence(cars)
}

AnySequence est une structure générique conforme à la norme Sequence qui transmet les à la séquence ou à l'itérateur sous-jacent à partir duquel il a été créé. Voir également Un peu de respect pour AnySequence pour d'autres exemples.

Remarques : De même, il est possible de faire Cars a Sequence en retournant un itérateur effacé par type qui transmet au tableau itérateur :

class Cars: Sequence {
    typealias Element = Car

    let cars: [Element]
    init(_ cars: [Element]) {
        self.cars = cars;
    }

    func makeIterator() -> AnyIterator<Element> {
        return AnyIterator(cars.makeIterator())
    }
}

1voto

simpleBob Points 3040

Le problème est que vous utilisez un générique pour un type spécifique. Vous pouvez soit retourner un Cars (notez que Cars est conforme à Sequence donc vous retournez un Sequence ici) :

func getCars(cars: [Car]) -> Cars {
    return  Cars(cars)
}

ou utiliser un générique (également un Sequence puisqu'il est défini dans le générique) :

func getCars<S: Sequence>(cars: [Car]) -> S {
    return cars as! S
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X