Programing Langauge/swift
rethrows
Hamp
2025. 9. 22. 13:14
반응형

🥊 rethrows
🎯 목표
아래 상황과 같이, 클로저에서 에러를 던질 때(throw)할 때, 어떻게 던질 수 있을까?
enum CustomError: Error {
case divideByZero
}
func divide(number: Int, divisor: Int) throws -> Int {
if divisor == .zero {
throw CustomError.divideByZero
}
return number / divisor
}
func calculate(function: (Int, Int) throws -> Int) {
throw function(10, 0) // ⚠️ Thrown expression type 'Int' does not conform to 'Error'
}
try calculate(function: divide)
⭐️ 역할
함수 파리미터에 throws 키워드가 있고, 에러를 현재 스코프가 아닌, caller쪽에 전달하고 싶을 떄 사용
😀 해결
enum CustomError: Error {
case divideByZero
}
func divide(number: Int, divisor: Int) throws -> Int {
if divisor == .zero {
throw CustomError.divideByZero
}
return number / divisor
}
func calculate(function: (Int, Int) throws -> Int) rethrows {
print(try function(10, 0))
}
do {
try calculate(function: divide)
} catch {
print("Error: \(error)")
}
✨ 특징
- rethrows 자리에 throws를 붙혀도 동작은 똑같다. 다만, 현재 함수에서 발생하는 erorr면 throws,
위와 같이 파라미터로 전달된 에러일 경우는 retrhows로 표시해, 구분하는 것이 좋다고한다. - 부모의 throws -> 자식의 rethorws로 재정의 ✅
- 부모의 rethrows -> 자식의 throws로 재정의 ❌
- 프로토콜의 throws -> 구현부 rethrows ✅
- 프로토콜의 retrhows -> 구현부 throws ❌
// MARK: - 부모 → throws
class Parent {
func doSomething(action: () throws -> Void) throws {
try action()
}
}
// ✅ 자식: throws → rethrows 로 완화 (허용)
class Child: Parent {
override func doSomething(action: () throws -> Void) rethrows {
print("Child: safely rethrows")
try action()
}
}
let parent: Parent = Child()
// Parent 타입이므로 호출자는 throws 기준으로 try 필요
try parent.doSomething {
print("Executing action") // 실제 실행은 rethrows 구현이지만 여전히 try 필요
}
// ===============================================================================================================
class Base {
func perform(action: () throws -> Void) rethrows {
try action()
}
}
❌ 컴파일 에러: 'throws'로 강화할 수 없음
class Sub: Base {
override func perform(action: () throws -> Void) throws {
Error: overriding rethrows with throws is not allowed
try action()
}
}
// ===============================================================================================================
// MARK: - 프로토콜 rethrows
protocol ReThrowingProtocol {
func execute(_ action: () throws -> Void) rethrows
}
// ❌ throws 로 구현하면 오류
struct WrongImpl: ReThrowingProtocol {
func execute(_ action: () throws -> Void) throws {
// Error: 'throws' function cannot satisfy 'rethrows' requirement
try action()
}
}
// ✅ 올바른 구현: rethrows 유지
struct CorrectImpl: ReThrowingProtocol {
func execute(_ action: () throws -> Void) rethrows {
try action()
}
}
// ===============================================================================================================
// MARK: - 프로토콜 throws
protocol ThrowingProtocol {
func run(_ action: () throws -> Void) throws
}
// ✅ rethrows 로 구현해도 throws 요구사항 충족
struct RethrowImpl: ThrowingProtocol {
func run(_ action: () throws -> Void) rethrows {
try action()
}
}
출처
Swift 3.0 의 throws, rethrows 에 대하여...
반년전즈음 스터디모임에서 Swift 3.0의 Array 에 대해 다루다가 map 이라는 함수를 보고 의문점이 생겼다. 분명히 내가 기억하기로는 Swift 2.2에서 Array의 map 함수는 Array.map(transform: T -> U) 이와 같이
redsubmarine.github.io
반응형