2015-01-07 12 views
9

Swift에는 추상 메소드가 없으므로, 기본 구현이 무조건 에러를 발생시키는 메소드를 생성하고 있습니다. 이것에 의해, 서브 클래스는 abstract 메소드를 오버라이드 (override)합니다.Swift는 던져진 함수로 인해 결코 돌아 오지 않을 것입니다. 예외

class SuperClass { 
    func shouldBeOverridden() -> ReturnType { 
     let exception = NSException(
      name: "Not implemented!", 
      reason: "A concrete subclass did not provide its own implementation of shouldBeOverridden()", 
      userInfo: nil 
     ) 
     exception.raise() 
    } 
} 

문제를 : 내 코드는 다음과 같은 함수가 값을 반환 할 것으로 예상된다 때문에, 그리고 위의 기능이 더 return 문이없는, 컴파일이 실패합니다. 나는이 함수가 항상 오류를 발생시키기 때문에 실행을 완료 할 수 없다는 것을 컴파일러에게 확신시키기 위해 어떤 방법이 필요하다.

모든 오류 처리가 라이브러리 수준으로 보이고 따라서 컴파일러를 이해할 수 없을 때 어떻게 Swift에서이 작업을 수행 할 수 있습니까? 프로그램의 실행을 (정상적으로) 끝내기위한 언어 수준의 기능이 있습니까?

+0

솔루션에 대한 질문에 스스로 답장을 해봤지만 잘못된/잘못된 문제를 해결하려고합니다. Swift에는 추상 메소드가 내장되어 있지 않은 이유가 있습니다. – nhgrif

답변

20

Swift의 @noreturn 속성은 함수와 메소드를 호출자에게 반환하지 않는 것으로 표시합니다. 로 아마 가장 간단한 예를

는 내장 함수의 서명 abort() 년대는 다음과 같습니다

@noreturn func abort() 

이 컴파일러에게이 필요로하는 모든 정보를 제공합니다. 예를 들어, 다음은 잘 컴파일 :

func alwaysFail() -> Int { 
    abort() 
} 

alwaysFail() 있지만이 이론적으로 Int 반환 스위프트 abort()가 호출 된 후 그 실행을 계속할 수 없습니다 알고있다.

원래의 코드가 작동하지 않는 이유는 NSException.raise이 사전 스위프트 방식이기 때문에 @noreturn 속성이 없기 때문입니다. 난 아직도 NSException를 사용하려면 내가 세 번째 옵션으로 적절한 속성

extension NSException { 
    @noreturn func noReturnRaise() { 
     self.raise() 
     abort() // This will never run, but Swift will complain that the function isn't really @noreturn if I don't call a @noreturn function before execution finishes. 
    } 
} 

과 확장을 정의 할 수 있습니다,

func shouldBeOverridden() -> ReturnType { 
    println("Subclass has not implemented abstract method `shouldBeOverridden`!") 
    abort() 
} 

또는 : 쉽게이 문제를 해결하기 위해, 나도 abort() 사용할 수 있습니다 컴파일러를 설득하기 위해 NSException.raise() 뒤에 절대 호출되지 않는 abort()을 사용할 수 있습니다.

func shouldBeOverridden() -> ReturnType { 
    let exception = NSException(
     name: "Not implemented!", 
     reason: "A concrete subclass did not provide its own implementation of shouldBeOverridden()", 
     userInfo: nil 
    ) 
    exception.raise() 
    abort() // never called 
} 
2

프로토콜을 만들고 shouldBeOverridden을 필수 방법으로 만든 다음 클래스가 해당 프로토콜을 준수하도록하는 것이 더 나은 방법이라고 생각됩니다. https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Protocols.html

+0

이 방법이 효과적 일 수 있지만 'SuperClass'의 공유 구현을 사용하여 가장 잘 구현되는 'SuperClass'의 모든 하위 클래스의 다른 요소가 있습니다.특히, 모든 "하위 클래스"(또는 제안에 따라 프로토콜을 준수하는 클래스)에 있어야하는 여러 저장된 속성이 있으며 모든 단일 하위 클래스에 대해 다시 선언하지 않아도됩니다. – SelectricSimian

+2

두 가지 방법을 결합하고 프로토콜과 기본 클래스를 결합하는 것이 좋습니다. 추상적 인 방법은 Objective-C 나 Swift에서 흔한 것이 아니며 프로토콜이 더 나은 선택이 아닌 경우를 찾지 못했습니다. Apple은 때때로이 조합 방법을 사용합니다 (UIBarPositioning 참조). –

+1

좋아, 그 정도로 잘 작동합니다. 조금 더 장황하게 보일 것 같지만 이해가되며 꽤 깨끗합니다. – SelectricSimian

8

엑스 코드에서 8 베타 6 (스위프트 3 베타 6) 지금 대신 @noreturnNever 반환 형식을 사용할 수 있습니다는 것을 나타 내기 : 이전 옵션은 extension 사용, 정말이 일을 단지 추상화입니다 함수가 호출자에게 반환되지 않습니다.

func crash() -> Never { 
    fatalError("Oops") 
}