2017-04-09 4 views
21

rethrowsの違いを理解するための便利で簡単な説明はありませんでした。どのように使用するべきかを理解しようとすると、混乱することがあります。スウィフトのスローとスローフードの違いは何ですか?

私は次のように私は、この種のエラーを伝播するための最も単純な形式での-Default- throwsに精通していますことを言及します:

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

をこれまでのところは良いが、問題は場合に発生する:

私がこれまで知っている
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 
} 

それはrethrowsとは異なり、tryによって扱われなければならthrows関数を呼び出すときです。だから何?! throwsまたはrethrowsを使用することを決定する際に私たちが従わなければならないロジックは何ですか?スウィフトの本の中で"Declarations"から

答えて

57

:関数やメソッドが にrethrowsキーワードで宣言することができ

再スローの関数とメソッド

は、それが唯一の1つがエラーをスローしたことを示しますそれは関数 のパラメータは、エラーをスローします。これらの関数とメソッドは、 再スロー関数再スロー方法として知られています。 Rethrowing関数と メソッドには、少なくとも1つのthrowing関数パラメータが必要です。 mapを呼び出すことができます変換非投げ、それが 自体がエラーをスローしないで呼び出され

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

場合tryなし::

典型的な例はmap方法であり、

// Example 1: 

let a = [1, 2, 3] 

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

let a1 = a.map(f1) 

しかし、mapが投げ閉めで呼び出された場合は、それ自体が を投げることができますdが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 { 
    // ... 
} 
  • mapthrows代わりのrethrowsとして宣言されたならば、あなたは が 、でも例1でtryでそれを呼び出す必要があります「不便」で、コードをbloatsました不要。
  • throws/rethrowsなしでmapが宣言された場合、 は例2のように投げ閉めで呼び出すことができませんでした。filter()index(where:)forEach()と多くのより多くの:

同じことが関数のパラメータを取るスウィフト標準ライブラリ から他の方法についても同様です。あなたのケースでは

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

はエラーをスロー関数であるのに対し、

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

は、 非投げ引数で呼び出された場合でも、エラーを投げることができる機能を表し 引数をスローすることで呼び出された場合のみです。

大雑把rethrowsは「自分で」 エラーを投げるが、唯一「前方」、その機能 パラメータからエラーがない関数のためである、話します。

+1

偉大な答え。ありがとう。 – Darko

+3

最後の文章は金色です! – Klaas

+1

だから私はそれを要約すると思います。あなたが**常に**投げに制限したいときは '投げる ' – Honey

7

Martinの答えに何かを追加するだけです。スロー機能と同じシグニチャーを持つスロー機能は、スロー機能のsub-typeとみなされます。それで、rethrowsはそれがどれであるかを判断でき、func paramでもthrowするが、投げていないのと同じ関数シグネチャを受け入れるときだけtryを要求する。 func paramがスローするときにdo tryブロックを使用するだけで便利ですが、関数内の他のコードはエラーをスローしません。

関連する問題