1

Having methods with different names for roughly the same task makes sense, for example

  • open(String filename);
  • createThenOpen(String filename); // First create the file with default contents, then process the file.

This naming approach does not work for constructors. Imagine the constructor takes a filename as above. I have various options to handle the two cases:

  1. If-statement in the constructor: if the file does not exist then create it. This is not nice as the behaviour of the constructor is implicit and the caller might create unwanted files instead of opening existing files.
  2. Add a flag to the constructor: MyClass(String filename, boolean createNew). Not very nice because a call like MyClass("hello.txt", true) is cryptic.
  3. Overload so that a single argument always assumes file exists, and the presence of an additional dummy parameter means the file should be created. This is also ugly.
  4. Add a String-flag as in RandomAccessFile(File file, String mode) where mode is "r", "rw" and so on. This feels very clunky for my purposes.
  5. Add an enum-flag similar to Files's copy(Path source, Path target, CopyOption... options). Feels pretty clunky too.
  6. Have constructor that takes no argument and then separate methods like above to be called immediately after the object is created. Not nice as it makes no sense to have an instance of my object without instantiating it using data from the specified file.

Currently I seem to actually favour number (6) above and simply have two methods with different names to be called immediately after a no-parameter constructor. Have I overlooked any options, or is there a "given" approach for these scenarios?

Edit: as pointed out by others below there is a 7th, perhaps most obvious option, of course:

  1. Use factory methods!
DustByte
  • 651
  • 6
  • 16
  • 1
    why not create a subclass which extends the behaviour with the creation of the file if it doesn't exist? – jonk Feb 02 '16 at 11:31
  • For option 2, make() does not sound like a very good constructor. It is meant to be the same as the class name, so what is your class name? – crowne Feb 02 '16 at 11:32
  • Using a subclass makes no sense as the superclass and subclass would represent exactly the same type of object. – DustByte Feb 02 '16 at 11:39

2 Answers2

2

Make your constructor with a long list of parameters protected, introduce a lot of public static named createFooWithBar() methods with precise parameter lists that call your constructor.

alamar
  • 18,729
  • 4
  • 64
  • 97
  • 1
    Argh! Yes, of course. Using SO is like writing down a mathematical proof for publication: you need to carefully formulate the proof for others in order to see the details, and discover its flaws. – DustByte Feb 02 '16 at 11:43
  • 1
    @DustByte using SO is like writing down proof and then receiving "you had an error but there I solved it for you" – alamar Feb 02 '16 at 11:48
  • @alamar - I wish reviewers or papers would be that helpful too. – DustByte Feb 02 '16 at 11:51
0

Make your constructor private and add public factory methods. This is a very common pattern, I think.

Another pattern is the "builder". Make the constructor accessible only to classes of the same package. Add in the same package a builder (or more than one builder if you prefer) that will call the constructor and call any other method necessary to construct your object.

Marco Altieri
  • 3,726
  • 2
  • 33
  • 47