Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

Sometimes you need to write a constructor which can fail. For instance, say I want to instantiate an object with a file path, something like

obj = new Object("/home/user/foo_file")

As long as the path points to an appropriate file everything's fine. But if the string is not a valid path things should break. But how?

You could:

  1. throw an exception
  2. return null object (if your programming language allows constructors to return values)
  3. return a valid object but with a flag indicating that its path wasn't set properly (ugh)
  4. others?

I assume that the "best practices" of various programming languages would implement this differently. For instance I think ObjC prefers (2). But (2) would be impossible to implement in C++ where constructors must have void as a return type. In that case I take it that (1) is used.

In your programming language of choice can you show how you'd handle this problem and explain why?

share|improve this question
1  
Exceptions in Java are one way of handling this. –  Mahmoud Hossam Mar 20 '11 at 19:29
    
C++ constructors don't return void - they return an object. –  gablin Mar 20 '11 at 20:59
5  
@gablin: Actually, that's not strictly true either. new calls operator new to allocate the memory, then the constructor to fill it. The constructor doesn't return anything, and new returns the pointer it got from operator new. Whether "doesn't return anything" implies "returns void" is up for grabs, though. –  Jon Purdy Mar 20 '11 at 21:16
    
@Jon Purdy: Hm, sounds reasonable. Good call. –  gablin Mar 21 '11 at 11:51
add comment

5 Answers 5

up vote 2 down vote accepted

It's never good to rely on a constructor to do the dirty work. Besides, it's also unclear to another programmer whether or not work is going to be done in the constructor unless there is explicit documentation stating so (and that the user's of the class have read it or been told so).

For example (in C#):

public Sprite
{
    public Sprite(string filename)
    {
    }
}

What happens if the user doesn't want to load the file straight away? What if they want to do on-demand caching of the file? They can't. You might think of putting a bool loadFile argument in the constructor, but then this makes this messy as you now still need a Load() method to load the file.

Given the current scenario, it's going to be more flexible and clearer to the users of the class to do this:

Sprite sprite = new Sprite();
sprite.Load("mario.png");

Or alternatively (for something like a resource):

Sprite sprite = new Sprite();
sprite.Source = "mario.png";
sprite.Cache();

// On demand caching of file contents.
public void Cache()
{
     if (image == null)
     {
         try
         {
             image = new Image.FromFile(Source);
         }
         catch(...)
         {
         }
     }
}
share|improve this answer
add comment

In Java, you could use exceptions or use the factory pattern, which would allow you to return null.

In Scala, you could return an Option[Foo] from a factory method. That would work in Java too, but would be more cumbersome.

share|improve this answer
    
Using Exceptions or factory in .NET languages too. –  Beth Whitezel Mar 20 '11 at 20:56
add comment

You could also instantiate the object with no parameters, or with only parameters which are sure never to fail, and then you use an initialization function or method from which you can safely thrown an exception or do whatever you wish.

share|improve this answer
5  
I think returning an unusable object that requires further initialization is the worst choice. Now you have a multiple-line fragment that has to be copied whenever the class is used, or factored into a new method. You may as well have the constructor do all the work and throw an exception if the object can't be constructed. –  kevin cline Mar 20 '11 at 21:09
2  
@kevin: Depends on the object. Failures will probably be due to external resources so an entity might want to register the intention (e.g. filename) but allow for repeated attempts to fully initialize. For a value object I'd probably lean towards reporting an error that can capture the underlying error, so probably throwing a (wrapped?) exception. –  Dave Mar 20 '11 at 22:25
add comment

Throw an exception.

Null needs to be checked for if you can return it ( and it won't be checked for)

This is what checked exceptions are for. You know it could fail. Callers have to handle this.

share|improve this answer
add comment

In C++, constructors are used to create/initialize members of the class.

There's no right answer to this question. But what I've observed so far, is that most of the times is the client (or whoever is going to use your API) who chooses how you should handle this stuff.

Sometimes they might ask you to allocate all the resources the object might need on the constructor and throw an exception if something fails (aborting the creation of the object), or do none of that on the constructor, and make sure the creation will always succeed, leaving these tasks for some member function to do.

If it's up to you to choose the behavior, exceptions are the default C++ way for handling errors and you should use them when you can.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.