2017-04-09 26 views
21

इसे समझने के लिए कुछ संदर्भों की खोज करने के बाद, दुर्भाग्य से- मुझे throws और 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 
} 

मैं अब तक क्या पता है जब एक समारोह है कि throws यह rethrows के विपरीत, एक try द्वारा नियंत्रित किया जाना है बुला रहा है। तो क्या?! तर्क क्या है कि हमें throws या rethrows का उपयोग करने का निर्णय लेने पर पालन करना चाहिए?

उत्तर

57
स्विफ्ट पुस्तक में

"Declarations" से:

Rethrowing कार्य और तरीके

एक समारोह या विधि को rethrows कीवर्ड के साथ घोषित किया जा सकता संकेत मिलता है कि यह एक त्रुटि फेंकता केवल तभी से एक यह कार्य पैरामीटर एक त्रुटि फेंकता है। इन कार्यों और विधियों को रीथ्रोइंग फ़ंक्शंस और रीथ्रोइंग विधियों के रूप में जाना जाता है। रेथ्रोइंग फ़ंक्शंस और विधियों में कम से कम एक फेंकने वाला फ़ंक्शन पैरामीटर होना चाहिए। 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 को फेंकने के बंद होने के साथ बुलाया जाता है तो वह को फेंक सकता है घ 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 के बजाय के रूप में घोषित किया गया आप यह जो "असुविधाजनक" है और कोड bloats, यहां तक ​​कि उदाहरण 1 में try साथ कॉल करने के लिए होता अनावश्यक।
  • यदि map को throws/rethrows के बिना घोषित किया गया था तो आप उदाहरण के रूप में इसे फेंकने वाले बंदरगाह के साथ कॉल नहीं कर सके।

ही स्विफ्ट स्टैंडर्ड लाइब्रेरी जो फ़ंक्शन पैरामीटर लेने से अन्य तरीकों के लिए सच है: filter(), index(where:), forEach() और कई कई और।

आपके मामले में,

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

, एक समारोह जो एक त्रुटि फेंक कर सकते हैं, एक गैर फेंक तर्क के साथ कॉल भले ही अर्थ है, जबकि

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

एक समारोह जो एक त्रुटि फेंकता को दर्शाता है केवल फेंकने वाले तर्क के साथ बुलाया जाता है।

मोटे तौर पर, rethrows कार्यों है जो त्रुटि "अपने दम पर" फेंक नहीं के लिए है, लेकिन केवल "आगे" त्रुटियों उनके कार्य मापदंडों से।

+1

ग्रेट उत्तर। धन्यवाद। – Darko

+3

आखिरी वाक्य सुनहरा है! – Klaas

+1

तो मुझे लगता है कि इसे समेटने के लिए, 'रीथ्रो' करें जब आप * फेंकना चाहते हैं। 'फेंक' जब आप ** हमेशा ** ** – Honey

7

मार्टिन के उत्तर के साथ कुछ जोड़ने के लिए बस। फेंकने वाले फ़ंक्शन के समान हस्ताक्षर वाले एक गैर फेंकने वाले फ़ंक्शन को फेंकने वाले फ़ंक्शन के sub-type माना जाता है। यही कारण है कि रीथ्रो यह निर्धारित कर सकते हैं कि यह कौन सा है और केवल try की आवश्यकता होती है जब func param भी फेंकता है, लेकिन फिर भी उसी फ़ंक्शन हस्ताक्षर को स्वीकार नहीं करता है जो फेंक नहीं देता है। फनक परम फेंकने पर केवल एक कोशिश करने का प्रयास करने का एक सुविधाजनक तरीका है, लेकिन फ़ंक्शन में अन्य कोड त्रुटि नहीं फेंकता है।

संबंधित मुद्दे