Core Java

Prestructors

Making constructors pre-process the arguments before encapsulating them seems to be bad practice. However, very often it’s necessary to do exactly that: perform some manipulations with the objects provided as arguments and only then assign them to the attributes of the constructed object. For this purpose I suggest using prestructors, which could be methods or stand-alone objects.

Huge in France (2019) by Gad Elmaleh et al.

Say, this is your code:

import java.util.List;
import java.util.Collections;
class Books {
  private final List<String> titles;
  Books(List<String> list) {
    this.titles = Collections.unmodifiableList(list);
  }
}

The only constructor expects a list of titles, which is being encapsulated as this.titles for some future use. It’s also protected against any accidental modifications, through the JDK decorator at unmodifiableList. So far, so good. Now, we want to make our class a bit smarter and let it accept not only the List but an array of strings:

class Books {
  private List<String> titles;
  Books(List<String> list) {
    this.titles = Collections.unmodifiableList(list);
  }
  Books(String... array) {
    final List<String> list = new ArrayList<>(array.length);
    for (final String title : array) {
      list.add(title);
    }
    this.titles = list;
  }
}

What’s wrong with this code? Those of you who have read my earlier blog posts about OOP most definitely know the answer. First, there are two primary constructors, which is another bad practice. Second, there is code in the second constructor, which is also a bad idea.

Here is how I usually refactor this code, to solve both mentioned problems:

class Books {
  private List<String> titles;
  Books(List<String> list) {
    this.titles = Collections.unmodifiableList(list);
  }
  Books(String... array) {
    this(Books.toList(array));
  }
  private static List<String> toList(String... array) {
    final List<String> list = new ArrayList<>(array.length);
    for (final String title : array) {
      list.add(title);
    }
    return list;
  }
}

I call this new static method toList() a prestructor: it is used only at the moment of object construction and only from the secondary constructor.

An even better way to design it would be to make a new class ToList, which would do exactly the same, but in a more declarative and lazy way:

class Books {
  private List<String> titles;
  Books(List<String> list) {
    this.titles = Collections.unmodifiableList(list);
  }
  Books(String... array) {
    this(new ToList(array));
  }
}
class ToList<T> implements List<T> {
  private final T[] array;
  ToList(T... items) {
    this.array = items;
  }
  // All required methods of the List interface
}

ListOf from Cactoos is a perfect example of such a prestructor.

Published on Java Code Geeks with permission by Yegor Bugayenko, partner at our JCG program. See the original article here: Prestructors

Opinions expressed by Java Code Geeks contributors are their own.

Yegor Bugayenko

Yegor Bugayenko is an Oracle certified Java architect, CEO of Zerocracy, author of Elegant Objects book series about object-oriented programing, lead architect and founder of Cactoos, Takes, Rultor and Jcabi, and a big fan of test automation.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button