难道我不能初始化参数列表,就像我可以设置一组值一样吗?

时间:2016-07-11 18:03:38

标签: scala

Scala已经支持这个:

val (a : Int, b: String, c: Double) = {
  val someInt : Int = 42 // ... complex computations ...
  val someString : String = "42" // ... complex computations ...
  val someDouble : Double = 42.0D // ... complex computations ...
  (someInt, someString, someDouble)
}

当我无法做到这一点时,我感到很惊讶:

class Foo(a : Int, b: String, c: Double) {
  def this(tuple: (Int, String, Double)) = {
    this {
      val someInt : Int = 42 // ... complex computations ...
      val someString : String = "42" // ... complex computations ...
      val someDouble : Double = 42.0D // ... complex computations ...
      (someInt, someString, someDouble)
    }
  }
}

编译器产生这个:

Error:(3, 6) called constructor's definition must precede calling
             constructor's definition
this {
^

我认为将构造函数的参数视为元组似乎很自然,但也许这只是我。我意识到我可以完成类似的事情 伴侣对象,但将逻辑置于类本身之外。

您是否知道如何进行复杂的计算"在不使用伴随对象的非主构造函数中?

1 个答案:

答案 0 :(得分:1)

What you do with

val (a : Int, b: String, c: Double) = someComputation

is, computing a value on the right side of the equal sign, and assign it to the name(s) on the left side of the equal sign.

What you do in the second example is

class Foo(a : Int, b: String, c: Double) {

you create a class with a default constructor taking three single parameters. If you like to think of it as a tuple or not, it simply is a parameter list with three single parameters.

Then with

def this(tuple: (Int, String, Double)) =

you try to define another constructor taking one parameter named "tuple" of type 3-tuple.

BUT

When you write something like this

def someName( aParam: TheType ) = { computation }

you declare a named function/method and its parameter list, then to the right of the equal sign you define its implementation.

The equal sign now is a marker, that the computation will not be without result, but indeed the result of the computation will be the result of the whole function/method.

So, you somehow may have to think in the other direction. The parameters flowing in from the left of the equal sign lead to a result to the right of the equal sign, where this "lead to" is defined by the computation.

One thing more: You can -and sometimes must- also leave off the equal sign:

def someMethod { someSideEffect }

This defines a method where nothing is returned.

At least until Scala 2.11, a constructor is of the last sort: It has no equal sign, as it does not return a value. Much more, as a side effect, it initialises the object under construction. That is, space for the object is allocated, and this space is initialised by executing the constructor's implementation with the given parameters.

So, coming back to your second example, with

def this(tuple: (Int, String, Double))

what you do is, declaring a constructor (an implementation to initialise an object under construction) taking one parameter named "tuple".

Now, in the code block following the declaration, you should define how to use the given tuple to initialise the object.

But what you do instead is

this {
  val someInt : Int = 42 // ... complex computations ...
  val someString : String = "42" // ... complex computations ...
  val someDouble : Double = 42.0D // ... complex computations ...
  (someInt, someString, someDouble)
}

i.e, you call the exactly same constructor with a value computed inside its implementation definition.

So, when this constructor is called with a tuple, you define that it should forget this tuple, but instead call that same constructor with another, computed, tuple, but by calling it, this newly created tuple will be forgotten, just to call that constructor with another, computed, tuple, but by calling it .....

This is confusing to the Scala-ist as well to the compiler. It does not know what indeed should happen when with what computations any more (and why ...). You declared something like a hen-and-egg problem to the compiler.

So tl;dr : NO.

The first example assigns values computed from the right side of '=' to the name(s) on the left side.

The second example defines a recursive constructor implementation, what simply is not possible in Scala.