The intersection of technology and leadership

Constructor work in Scala

In the java/ruby world, I am used to ensuring my objects are created in a valid state. This often means validating/converting constructor arguments into a format necessary for the rest of the class to do its work. In java, the code (non-compilable) might look like:

public class MyObject {
  ...

  public MyObject(Set<String> values) {
     this.internalRepresentation = convertToLowerCase(values)
  }

  ...
}

In scala, most examples out there seem to only chain constructors, and not necessarily do any work to that. I looked on stackoverflow and found this answer although it doesn’t feel particularly clean to me for some reason. My scala code now looks like this:

class MyObject(var values: Set[String]) {
  values = values.map(s => s.toLowerCase)
  ...
}

What I don’t like about this is that I had to elevate my field to being mutable, or had to have two immutable fields on the class (the temporary one for the constructor, and the one that I really want to use). The tests are passing, but I’m sure there is a better way.

6 Comments

  1. Andy Palmer

    Mutability is more a statement of intention than an absolute requirement.
    In Ruby, everything is mutable, but that doesn’t mean we have to write setters for our internal variables (even if someone can come along and add one later)

    If you want your values to be lowercased, I’d go for the mutable internal variable, and use intention to ensure that it remains unchanged after initialisation 🙂

    There’s a reason why I detest sealed classes in c# 🙂

  2. Arnon Rotem-Gal-Oz

    You can use a
    class MyObject(private val valueParam: Set[String]) {
    lazy val values = valueParam.map(s => s.toLowerCase)l

    Arnon

  3. Patrick

    @Arnon – Thanks. I guess that is an option but have to create two names for the same variable.

    @Andy – Agree that mutability is about intention. I’ll probably change the implementation at some point. I think I dislike sealed classes in C# just because they are too verbose.

    Thanks for the comments.

  4. Jessitron

    It is correct to have two names here. The constructor argument has a different meaning than the member; they have different ranges of valid values. Arnon is right.

  5. Uday

    I would put any logic that is required to create a valid object into a constructor in companion object. And also make the constructor on the class as private. (Same as the example mentioned in the stackoverflow link you mentioned).

    Is there any reason why you think this approach is not clean?

    – Uday.

  6. Patrick

    Thanks for the comments @Jessitron & @Uday

    @Jessitron I’m not sure what you mean by “correct” as it is always contextual around what is more readable and intent. Thus, when humans involved I rarely see “correctness” 😉

    @Uday I’m currently uncomfortable with the idea of a companion object because I think it makes ideas less cohesive (you have more things related to the same concept lying around in different places). When I write OO, I try to balance out reducing coupling and maintaining cohesion. When doing ruby for instance, I find you end up with less classes because it’s simpler to keep things in the same spot for a variety of rasons (more cohesion) but that deserves a different blog on its own. Once again, clean is contextual. Maybe this video might make more sense as Greg Young can rant much better than I can.

Leave a Reply

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

© 2024 patkua@work

Theme by Anders NorenUp ↑