2017-04-09 9 views
21

Nach der Suche nach einigen Referenzen, um herauszufinden, - leider - ich konnte nicht nützlich finden - und einfache Beschreibung über das Verständnis der Unterschiede zwischen throws und rethrows. Es ist etwas verwirrend, wenn Sie versuchen zu verstehen, wie wir sie verwenden sollten.Was sind die Unterschiede zwischen Würfen und Wiederholungen in Swift?

Ich würde erwähnen, dass ich bin ein bisschen vertraut mit dem -Default- throws mit seiner einfachsten Form für einen Fehler propagieren, wie folgt:

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

So weit so gut, aber das Problem tritt auf, wenn:

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 
} 

, was ich bisher weiß, ist, wenn eine Funktion aufrufen, die throws es von einem try behandelt werden muss, im Gegensatz zu den rethrows. Na und?! Was ist eine Logik, der wir bei der Entscheidung, throws oder rethrows zu verwenden, folgen sollten?

Antwort

57

Von "Declarations" im Swift Buch:

Erneutes Auslösen von Funktionen und Methoden

Eine Funktion oder Methode kann mit dem rethrows Schlüsselwort deklariert werden zeigen, dass es einen Fehler nur, wenn man wirft die es ist Funktion Parameter wirft einen Fehler. Diese Funktionen und Verfahren sind bekannt als Nachfolgefunktionen und Nachfolgeverfahren. Wiederholungsfunktionen und Methoden müssen mindestens einen Wurffunktionsparameter haben.

Ein typisches Beispiel ist die map Methode:

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

Wenn map mit einem nicht-Wurf verwandeln genannt wird, es nicht selbst einen Fehler wirft und ohne try genannt werden können:

// Example 1: 

let a = [1, 2, 3] 

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

let a1 = a.map(f1) 

Aber wenn map mit einem werfenden Verschluss aufgerufen wird, kann sich selbst anwerfen d muss mit try aufgerufen werden:

// 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 { 
    // ... 
} 
  • Wenn map als throws statt rethrows erklärt wurden dann würden Sie haben es zu nennen mit try auch in Beispiel 1, die „unbequemen“ ist und bläht den Code nicht notwendig.
  • Wenn map ohne throws/rethrows deklariert wurden, dann konnte man nicht mit einem Wurfverschluss wie in Beispiel 2 nennen.

Das gleiche gilt für andere Methoden der Swift Standard Library die Funktionsparameter nehmen: filter(), index(where:), forEach() und viele viele mehr.

In Ihrem Fall

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

bezeichnet eine Funktion, die einen Fehler auslösen kann, auch wenn mit ein nicht-Wurf Argumente genannt, während

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

eine Funktion bezeichnet, die einen Fehler auslöst nur wenn mit einem Wurfargument aufgerufen.

sprechen Grob rethrows für Funktionen, die nicht Fehler „auf eigene Faust“ werfen, aber „vorwärts“ Fehler von ihrer Funktion Parameter nur.

+1

Große Antwort. Vielen Dank. – Darko

+3

Der letzte Satz ist golden! – Klaas

+1

Ich denke, um es zusammenzufassen, 'retrow' wenn du * werfen * willst. 'throw' wenn du ** immer auf ** werfen willst – Honey

7

Nur um etwas mit Martins Antwort hinzuzufügen. Eine Nicht-Wurf-Funktion mit der gleichen Signatur wie eine Wurf-Funktion wird als sub-type der Wurf-Funktion betrachtet. Aus diesem Grund kann rethrows bestimmen, welche es ist und nur try erfordern, wenn der func param auch wirft, aber immer noch die gleiche Funktionssignatur akzeptiert, die nicht wirft. Es ist eine bequeme Möglichkeit, nur einen do try-Block zu verwenden, wenn der func-param-Befehl ausgelöst wird, aber der andere Code in der Funktion gibt keinen Fehler aus.

Verwandte Themen