Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala extra no-arg constructor plus default constructor parameters

I am using the Scala 2.8 default parameters on a constructor, and for Java compatibility reasons, I wanted a no-arg constructor that uses the default parameters.

This doesn't work for very sensible reasons:

class MyClass(field1: String = "foo", field2: String = "bar") {
    def this() = {
        this() // <-- Does not compile, but how do I not duplicate the defaults?
    }
}

I am wondering if there is anything that I am missing. Any thoughts that don't require duplicating the parameter defaults?

Thanks!

like image 540
jkl Avatar asked Oct 28 '10 18:10

jkl


People also ask

Are no-arg constructor and default constructor same?

Answer to your question is No. Java won't provide a default constructor if you write any kind of constructor in class. One difference between them is that the body of default constructor will always be empty whereas we can insert our own code in no-arg constructor.

What is the purpose for the no-arg constructor?

In Java, a no-argument constructor is the default constructor and if you don't define explicitly in your program. Then Java Compiler will create a default constructor with no arguments. The purpose is to call the superclass constructor.

What are auxiliary constructors in Scala?

The auxiliary constructor in Scala is used for constructor overloading and defined as a method using this name. The auxiliary constructor must call either previously defined auxiliary constructor or primary constructor in the first line of its body.

Does Jackson need no-arg constructor?

Jackson won't use a constructor with arguments by default, you'd need to tell it to do so with the @JsonCreator annotation. By default it tries to use the no-args constructor which isn't present in your class.


3 Answers

I wouldn't really recommend it, but you can do it by adding another parameter to your constructor:

class MyClass(a: String = "foo", b: String = "bar", u: Unit = ()) {
  def this() { this(u = ()) }
}

Unit is a good choice because you can only pass one thing into it anyway, so explicitly passing the default value doesn't allow any possibility of error, and yet it lets you call the correct constructor.

If you're willing to replicate just one of the defaults, you can use the same strategy except override that one chosen default instead of adding the unit parameter.

like image 183
Rex Kerr Avatar answered Oct 22 '22 17:10

Rex Kerr


As curious work-around hack, and I do mean hack: you can use the internal representation of default arguments:

class MyClass(field1: String = "foo", field2: String = "bar") { 
  def this() =  this(MyClass.init$default$1)
}

Notice that it's needed to include MyClass in this(MyClass.init$default$1). A partial explanation is that the default arguments are kept in companion objects.

like image 30
pedrofurla Avatar answered Oct 22 '22 19:10

pedrofurla


You might consider using a factory method:

class MyClass(field1: String = "foo", field2: String = "bar")
object MyClass {
    def newDefaultInstance = new MyClass
}

Then from Java you can call MyClass.newDefaultInstance()

Another possibility is to move where you specify the default values:

class MyClass(field1: String, field2: String) {
  def this() = this(field1="foo", field2="bar")
}

This style is especially useful if you're working with a framework such as Spring which uses reflection to locate a 0-arg constructor.

like image 40
Kevin Wright Avatar answered Oct 22 '22 17:10

Kevin Wright