Steve Perkins
Steve Perkins

Reputation: 11860

Implementing a single Scala constructor that does more than set variables

Most of the time, a constructor for a class does nothing more than take its argument values and use them to set instance variables:

// Java
public class MyClass {
   private int id;

   public MyClass(int id) {
      this.id = id;
   }
}

So I understand the efficiency of Scala's default constructor syntax... simply declaring a list of variables in parentheses beside the class name:

// Scala
class MyClass(id: int) {
}

However, what about those circumstances where you need a constructor to actually DO STUFF, apart from simply plugging arguments into instance variables?

// Java
public class MyClass {
   private String JDBC_URL = null;
   private String JDBC_USER = null;
   private String JDBC_PASSWORD = null;

   public MyClass(String propertiesFilename) {
      // Open a properties file, parse it, and use it to set instance variables.
      // Log an error if the properties file is missing or can't be parsed.
      // ...
   }
}

How does this work in Scala? I can try to define an implementation for this constructor like so:

// Scala
class MyClass(propertiesFilename: String) {
  def this(propertiesFilename: String) {
    // parse the file, etc
  }
}

... but I get a compilation error, complaining that the constructor is defined twice.

I could avoid this conflict by having a no-arg default constructor, and then declaring the above as an overloaded secondary constructor. However, what about situations in which you really DO need "one-and-only-one" constructor, and you need it to do stuff?

Upvotes: 17

Views: 7713

Answers (2)

Dirk
Dirk

Reputation: 31053

You can perform these actions simply in the class body.

Class Foo(filename: String) {
    val index =  {
         val stream = openFile(filename)
         readLines(stream)
         ...
         someValue
     }
     println(“initialized...“) 
}

Upvotes: 27

Didier Dupont
Didier Dupont

Reputation: 29528

Any code you put in the body of the class is executed at construction

class MyClass(propertiesFileName: String) {
  println("Just created an instance of MyClass with properties in " + propertiesFileName)
  val myFavoriteProperty = retrieveFavoriteFrom(propertiesFileName)
}

It may be a little awkward and it is certainly not a good idea to interleave your member declaration and your initialization code a lot, but it is a small price to pay for the the convenience of the variable initialization syntax

Upvotes: 6

Related Questions