108 votes

Quelles sont les différences entre les lancers et les relances dans Swift?

Après la recherche de quelques références à la figure, malheureusement je ne pouvais pas trouver utile et simple - description sur la compréhension des différences entre throws et rethrows. C'est un peu déroutant lorsque vous essayez de comprendre comment nous devrions les utiliser.

Je tiens à mentionner que je suis un peu familier avec l'-par défaut- throws avec sa forme la plus simple de propagation d'une erreur, comme suit:

enum CustomError: Error {
    case potato
    case tomato
}

func throwCustomError(_ string: String) throws {
    if string.lowercased().trimmingCharacters(in: .whitespaces) == "potato" {
        throw CustomError.potato
    }

    if string.lowercased().trimmingCharacters(in: .whitespaces) == "tomato" {
        throw CustomError.tomato
    }
}

do {
    try throwCustomError("potato")
} catch let error as CustomError {
    switch error {
    case .potato:
        print("potatos catched") // potatos catched
    case .tomato:
        print("tomato catched")
    }
}

C'est très bien, mais le problème se pose lorsque:

func throwCustomError(function:(String) throws -> ()) throws {
    try function("throws string")
}

func rethrowCustomError(function:(String) throws -> ()) rethrows {
    try function("rethrows string")
}

rethrowCustomError { string in
    print(string) // rethrows string
}

try throwCustomError { string in
    print(string) // throws string
}

ce que je sais, c'est quand l'appel d'une fonction qui throws il doit être manipulé par un try, contrairement à l' rethrows. Et alors?! Quelle est la logique que nous devrions suivre avant de décider d' throws ou rethrows?

233voto

Martin R Points 105727

De "Déclarations" de la Swift livre:

Renvoi des Fonctions et des Méthodes

Une fonction ou une méthode peut être déclarée avec l' rethrows mot-clé à indiquer qu'il déclenche une erreur si l'une de leur fonction. les paramètres de renvoi d'une erreur. Ces fonctions et ces méthodes sont connues comme renvoi des fonctions et de renvoi des méthodes. Renvoi des fonctions et les méthodes doivent avoir au moins un lancer paramètre de la fonction.

Un exemple typique est l' map méthode:

public func map<T>(_ transform: (Element) throws -> T) rethrows -> [T]

Si map est appelée avec un non-lancer transformer, il ne jette pas une erreur elle-même et peut être appelée sans try:

// Example 1:

let a = [1, 2, 3]

func f1(n: Int) -> Int {
    return n * n
}

let a1 = a.map(f1)

Mais si map est appelée avec un lancer de fermeture alors lui-même pouvez jeter et doit être appelée avec try:

// Example 2:

let a = [1, 2, 3]
enum CustomError: Error {
    case illegalArgument
}

func f2(n: Int) throws -> Int {
    guard n >= 0 else {
        throw CustomError.illegalArgument
    }
    return n*n
}


do {
    let a2 = try a.map(f2)
} catch {
    // ...
}
  • Si map ont été déclarés throws au lieu de rethrows alors vous faut l'appeler avec try même dans l'exemple 1, qui est "gênant" et gonfle le code inutile.
  • Si map ont été déclarés sans throws/rethrows alors que vous pourriez ne pas appeler avec un lancer de fermeture comme dans l'exemple 2.

La même chose est vraie pour les autres méthodes de la Swift de la Bibliothèque Standard qui prennent des paramètres de fonction: filter(), index(where:), forEach() et beaucoup de beaucoup plus.

Dans votre cas,

func throwCustomError(function:(String) throws -> ()) throws

indique qu'une fonction peut renvoyer une erreur, même si elle est appelée avec un non-lancer argument, alors que la

func rethrowCustomError(function:(String) throws -> ()) rethrows

désigne une fonction qui renvoie une erreur uniquement si la fonction est appelée avec un jeter argument.

Grosso modo, rethrows est pour les fonctions qui ne sont pas de jeter les erreurs "sur leur propre", mais seulement "en avant" les erreurs de leur fonction les paramètres.

19voto

JustinM Points 1377

Juste pour ajouter quelque chose le long avec Martin réponse. Non lancer la fonction avec la même signature jeter fonction est considérée comme un sub-type de lancer la fonction. C'est pourquoi, renvoie peut déterminer qui il est et ne nécessitent try lorsque la touche func param aussi les lancers, mais accepte toujours la même signature de fonction qui n'est pas à jeter. C'est un moyen pratique de n'avoir à utiliser un faire bloc try lorsque la touche func param lancers, mais l'autre code dans la fonction ne renvoie pas d'erreur.

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