Can't I define defaults if I define multiple o

2019-06-15 01:00发布

问题:

I've defined multiple constructors, with some default argument values in all of them. Looks correct (I can't see any ambiguity), but Scala (2.8) compiler complains:

multiple overloaded alternatives of constructor define default arguments

Does it mean that I can't define default values for overloaded constructors at all?

Let me illustrate the situation (primitivized, of course, but illustrative):


class A(subject : Double, factor : Int = 1, doItRight : Boolean = true) {

  def this (subject : Int, factor : Int = 1, doItRight : Boolean = true) = {
    this(subject.toDouble , factor, doItRight)
  }

  def this (subject : String, factor : Int = 1, doItRight : Boolean = true) = {
    this(subject.toDouble , factor, doItRight)
  }

  def this () = {
    this(defaultSubject)
  }

}



回答1:

Taken straight from the compiler's source code:

// only one overloaded alternative is allowed to define default arguments

In general, I wouldn't advise that you mix overloading and defaults. Even if there's no conflict it can make your code harder to read.

UPDATE

Since you added code, it's clear now that you don't want/need to override the default values for each secondary constructor. In your particular case, I might even question the need for those extra constructors at all; Int=>Double is already available for you as an implicit conversion and String=>Double looks like you might be perverting the type system :)

Also... As an alternative to overloaded constructors, you can define just the primary constructor with defaults, then overload the apply method of the companion object and use that as a factory. This is of course completely optional, but it's rapidly becoming established as a pattern through the use of case classes.



回答2:

The overloading fails because you (unnessesarily) define multiple constructors with default values. Do this instead:

class A(subject : Double, factor : Int = 1, doItRight : Boolean = true) {

  def this (subject : Int) = {
    this(subject.toDouble)
  }

  def this (subject : String) = {
    this(subject.toDouble)
  }

  def this () = {
    this(defaultSubject)
  }
}