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

Gel*_*ion 0 scala

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

case class HadoopFsRelation(location: FileIndex, ...)(val sparkSession: SparkSession)
Run Code Online (Sandbox Code Playgroud)

我想知道为什么它具有采用 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())
Run Code Online (Sandbox Code Playgroud)

}

那么问题是使用这种结构有什么意义以及为什么在 Scala 中允许它?

Jör*_*tag 5

大多数其他编程语言只允许一个参数列表(或者,在 Haskell 的情况下,甚至只有一个参数),Scala 允许多个参数列表,每个参数列表都有多个参数。

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

  • 如果一个参数列表只有一个参数,那么这个参数对应的参数可以作为一个“块”在花括号中传递,这在这个参数是一个函数或偏函数的情况下特别有用。
  • 多参数列表是 Scala 的柯里化方法,即你可以省略最后一个参数列表,你会得到一个部分应用的函数。
  • 类型推断在参数列表之间从左到右流动,但不在参数列表内。因此,分离参数列表可以帮助类型推断并减少所需类型注释的数量。
  • 参数列表中引入的标识符在右侧的参数列表中。这允许您使用路径相关的方法类型,其中后面的参数列表中的参数类型取决于前面的参数列表中的参数值。
  • 只能标记整个参数列表implicit。如果您希望某些参数显式而某些参数隐式,则需要将隐式参数分离到单独的参数列表中。
  • 参数列表中只有一个参数可以是重复参数。如果您想要多个重复的参数,则需要将它们分开到单独的参数列表中。

这个只适用于构造函数,更具体地说,仅适用于主构造函数,更具体地说,仅适用于 case 类的主构造函数:

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

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