When is it right for a constructor to throw an exception?

前端 未结 24 818
时光取名叫无心
时光取名叫无心 2020-11-30 16:47

When is it right for a constructor to throw an exception? (Or in the case of Objective C: when is it right for an init\'er to return nil?)

It seems to me that a cons

相关标签:
24条回答
  • 2020-11-30 17:15

    Yes, if the constructor fails to build one of its internal part, it can be - by choice - its responsibility to throw (and in certain language to declare) an explicit exception , duly noted in the constructor documentation.

    This is not the only option: It could finish the constructor and build an object, but with a method 'isCoherent()' returning false, in order to be able to signal an incoherent state (that may be preferable in certain case, in order to avoid a brutal interruption of the execution workflow due to an exception)
    Warning: as said by EricSchaefer in his comment, that can bring some complexity to the unit testing (a throw can increase the cyclomatic complexity of the function due to the condition that triggers it)

    If it fails because of the caller (like a null argument provided by the caller, where the called constructor expects a non-null argument), the constructor will throw an unchecked runtime exception anyway.

    0 讨论(0)
  • 2020-11-30 17:17

    Eric Lippert says there are 4 kinds of exceptions.

    • Fatal exceptions are not your fault, you cannot prevent them, and you cannot sensibly clean up from them.
    • Boneheaded exceptions are your own darn fault, you could have prevented them and therefore they are bugs in your code.
    • Vexing exceptions are the result of unfortunate design decisions. Vexing exceptions are thrown in a completely non-exceptional circumstance, and therefore must be caught and handled all the time.
    • And finally, exogenous exceptions appear to be somewhat like vexing exceptions except that they are not the result of unfortunate design choices. Rather, they are the result of untidy external realities impinging upon your beautiful, crisp program logic.

    Your constructor should never throw a fatal exception on its own, but code it executes may cause a fatal exception. Something like "out of memory" isn't something you can control, but if it occurs in a constructor, hey, it happens.

    Boneheaded exceptions should never occur in any of your code, so they're right out.

    Vexing exceptions (the example is Int32.Parse()) shouldn't be thrown by constructors, because they don't have non-exceptional circumstances.

    Finally, exogenous exceptions should be avoided, but if you're doing something in your constructor that depends on external circumstances (like the network or filesystem), it would be appropriate to throw an exception.

    Reference link: https://blogs.msdn.microsoft.com/ericlippert/2008/09/10/vexing-exceptions/

    0 讨论(0)
  • 2020-11-30 17:17

    There is generally nothing to be gained by divorcing object initialization from construction. RAII is correct, a successful call to the constructor should either result in a fully initialized live object or it should fail, and ALL failures at any point in any code path should always throw an exception. You gain nothing by use of a separate init() method except additional complexity at some level. The ctor contract should be either it returns a functional valid object or it cleans up after itself and throws.

    Consider, if you implement a separate init method, you still have to call it. It will still have the potential to throw exceptions, they still have to be handled and they virtually always have to be called immediately after the constructor anyway, except now you have 4 possible object states instead of 2 (IE, constructed, initialized, uninitialized, and failed vs just valid and non-existent).

    In any case I've run across in 25 years of OO development cases where it seems like a separate init method would 'solve some problem' are design flaws. If you don't need an object NOW then you shouldn't be constructing it now, and if you do need it now then you need it initialized. KISS should always be the principle followed, along with the simple concept that the behavior, state, and API of any interface should reflect WHAT the object does, not HOW it does it, client code should not even be aware that the object has any kind of internal state that requires initialization, thus the init after pattern violates this principle.

    0 讨论(0)
  • 2020-11-30 17:17

    I'm just learning Objective C, so I can't really speak from experience, but I did read about this in apple's docs.

    http://developer.apple.com/documentation/Cocoa/Conceptual/CocoaFundamentals/CocoaObjects/chapter_3_section_6.html

    Not only will it tell you how to handle the question you asked, but it does a good job of explaining it as well.

    0 讨论(0)
  • 2020-11-30 17:18

    It's reasonable for a constructor to throw an exception so long as it cleans itself up properly. If you follow the RAII paradigm (Resource Acquisition Is Initialization) then it is quite common for a constructor to do meaningful work; a well-written constructor will in turn clean up after itself if it can't fully be initialized.

    0 讨论(0)
  • 2020-11-30 17:19

    Because of all the trouble that a partially created class can cause, I'd say never.

    If you need to validate something during construction, make the constructor private and define a public static factory method. The method can throw if something is invalid. But if everything checks out, it calls the constructor, which is guaranteed not to throw.

    0 讨论(0)
提交回复
热议问题