Scala extra no-arg constructor plus default constructor parameters
Asked Answered
J

5

9

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!

Jeaniejeanine answered 28/10, 2010 at 18:8 Comment(2)
there's a ticket at lampsvn.epfl.ch/trac/scala/ticket/4278Jacobsohn
I spoke up in favor of that ticket at my first ever in-the-flesh scala meeting and said flesh was consumed by ravenous "don't go ruining the language with your special cases" wolves. It's every use case for himself now!Impetuosity
F
12

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.

Fromenty answered 28/10, 2010 at 18:28 Comment(1)
I agree that this is in the spirit of my question (minimizing duplication), but not a great practice. Thanks for the answer!Jeaniejeanine
R
4

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.

Rotterdam answered 29/10, 2010 at 1:28 Comment(0)
C
4

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.

Columbary answered 29/10, 2010 at 8:32 Comment(1)
Thanks for the ideas. In my exact case, the first wouldn't work as this is a Servlet that I am initializing (so I need the no-arg.) The second is feasible, but I lose the pleasant defaulting behavior in tests that the default values were providing. I would have likely turned to the first had I not needed the no-arg constructor...Jeaniejeanine
P
0

Not suitable for all purposes, but a subclass might do the trick:

class DefaultMyClass extends MyClass()
Photostat answered 21/2, 2011 at 20:54 Comment(0)
H
0

If I am not wrong in understanding the question, following code worked very well for me`

class Employee (

   ){
  def this( name :String ,

    eid :Int ){
    this();
  }
}

`

Hutchinson answered 9/6, 2017 at 13:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.