当我编译以下代码时,它会失败并抛出错误:
主测试。scala:11:错误:对象maintest中读取的方法缺少参数列表
object GenericTest {
def createStream[T: ClassTag](endpoint: String, shardId: Int, func: RecordEntry => T): DStream[T] = {
null
}
def createStream[T: ClassTag](endpoint: String,func: RecordEntry => T): DStream[T] = {
null
}
}
object MainTest {
def main(args: Array[String]): Unit = {
val ddd = GenericTest.createStream[String]("6", 1, read)
}
def read(record: RecordEntry): String = {
s"${record.getString(0)},${record.getString(1)}"
}
}
如果我删除generictest中的第二个方法createstream,那么maintest可以成功编译。或者,如果我修改maintest如下(在调用generictest.createstrem()时删除“[string]”,它可以成功编译。
def main(args: Array[String]): Unit = {
//remove the "[String]"
val ddd = GenericTest.createStream("6", 1, read)
}
或者,如果我修改maintest如下(添加红色convert to func),它可以成功编译。
def main(args: Array[String]): Unit = {
// add the " _" after read parameter
val ddd = GenericTest.createStream[String]("6", 1, read _)
}
你知道这个问题吗,为什么会失败?正确的方法应该是什么样的?
2条答案
按热度按时间mfuanj7w1#
该错误是由于尝试将方法作为函数传递引起的。一种方法,如
read
,与对象相关联,因此不能将其作为裸函数调用。表达式
read _
被称为eta的扩展read
它基本上把MainTest
反对read
方法来创建裸函数。所以在问题的最后一段代码中已经有了正确的方法。
那么,为什么它在没有
_
如果只有一个版本createStream
?错误消息显示:
只有在需要函数类型时,未应用的方法才会转换为函数。
换言之,如果您在一个方法知道它需要函数时传递该方法,编译器将自动执行此转换。
当有单一版本的
createStream
编译器可以将提供的值与该方法的参数匹配。它知道一个函数RecordEntry => T
是必需的,因此它执行从方法到函数的转换(eta展开)。当有多个重载版本的
createStream
编译程序必须首先确定调用哪个版本。它将值的数量和类型与每个版本的参数的数量和类型进行比较createStream
. 在这种情况下,没有对手func
因为类型是错误的:它是一个方法而不是一个函数。因此,当存在重载方法时,必须将该方法转换为相应重载方法所需的类型。6jjcrrmo2#
编译错误说明
所以请两者都做
或者