Scala中每个参数的单独构造函数

时间:2019-02-24 13:03:17

标签: scala

我试图从Apache Spark的源代码中了解以下类声明:

case class HadoopFsRelation(location: FileIndex, ...)(val sparkSession: SparkSession)

我想知道为什么它有第二个采用SparkSession的构造函数。

我只是写了一些例子来澄清一些要点:

class Person(firstName: String)(lastName: String)(val age: Int) {
  def tellMeAboutYourSelf() = {
   //basically I have access to all three arguments
   s"$firstName, $lastName - $age"
  }
}

object Main extends App {
//no errors are shown, though it fails during compilation:
//missing argument lis for constructor Person
val singleArg: Person = new Person("Harry")

//surprisingly no errors are shown but it also fails during compilation:
//Person does not take parameters
val twoArgsCurrying: Person = singleArg("Potter")

//no errors, and the same compilation failure
//missing argument list for constructor Person
//a pure expression does nothing in statement position; you may be omitting necessary parentheses
val harry: Person = new Person("Harry")("Potter"){100}

//finally this works
val harry: Person = new Person("Harry")("Potter")(100)
println(harry.tellMeAboutYourSelf())

}

那么问题是使用这种构造有什么意义,为什么在Scala中允许使用这种构造?

2 个答案:

答案 0 :(得分:4)

这不是不同的构造函数。这是具有多个参数列表的单个构造函数。

https://docs.scala-lang.org/tour/multiple-parameter-lists.html

方法中的多个参数列表主要用于循环/部分应用。

对于一个案例,第一个列表中的类参数是val(即在类外部可以访问)。

答案 1 :(得分:4)

与大多数其他仅允许一个参数列表的编程语言不同(例如,对于Haskell,甚至只允许一个参数),Scala允许多个参数列表,每个参数列表具有多个参数。

使用多个参数列表的原因有很多:

  • 如果参数列表中只有一个参数,则可以将该参数所对应的参数以大括号形式传递为“块”,这在该参数是函数或部分函数的情况下特别有用。 li>
  • 多个参数列表是Scala的计算方法,即,您可以省略最后一个参数列表,而获得部分应用的函数。
  • 类型推断在参数列表之间从左到右流动,但不在参数列表内。因此,分隔参数列表可以帮助进行类型推断,并减少所需的类型注释。
  • 参数列表中引入的标识符在右侧参数列表的范围内。这样,您便可以使用路径相关的方法类型,其中后一个参数列表中的参数类型取决于前一个参数列表中的参数值。
  • 只能将整个参数列表标记为implicit。如果希望某些参数是显式的而某些参数是隐式的,则需要将这些隐式参数分开到单独的参数列表中。
  • 参数列表中的一个参数只能是重复的参数。如果您需要多个重复的参数,则需要将它们分成单独的参数列表。

这仅适用于构造函数,更具体地说仅适用于主构造函数,甚至更仅适用于案例类的主要构造函数:

  • 第一个参数列表的参数被视为“特殊”:
    • 它们自动成为public val的访问者。
    • 它们用于生成##的明智的默认实现
    • 它们用于生成==的明智的默认实现
    • 案例类将扩展ProductN[A, … Z],其中A, … Z是第一个参数列表的参数类型。
    • 将有一个自动生成的同名对象,该对象扩展了FunctionN[A, … Z]并具有一个apply方法,其唯一参数列表与该对象的主要构造函数的第一个参数列表相同。案例类。

因此,如果您不希望其中任何一个参数都需要,则需要将该参数放入单独的参数列表中。