Scala中如何结合Function接口与隐式参数定义函数对象?
带隐式参数的Scala函数对象实现方案
这个问题其实是因为Scala标准库的函数类型(比如A => B)只对应单参数列表、无隐式参数的apply方法,而你想要的是带隐式参数的多参数列表apply,所以不能直接用标准函数类型来继承。下面给你两种可行的实现方式:
方法一:自定义函数类型特质(推荐)
直接定义一个包含目标apply方法签名的特质,让你的object继承这个特质即可,这是最贴合你需求的写法:
import org.apache.spark.sql.{DataFrame, SparkSession} // 先定义自定义的函数类型特质,匹配带隐式参数的apply方法签名 trait ConfigToDataFrame { def apply(config: Configuration)(implicit sparkSession: SparkSession): DataFrame } // 实现你的函数对象 object DoSomething extends ConfigToDataFrame { override def apply(config: Configuration)(implicit sparkSession: SparkSession): DataFrame = { val bootstrapServers = config.bootstrapServers val topic = config.topic sparkSession.readStream .format("kafka") .option("kafka.bootstrap.servers", bootstrapServers) .option("subscribe", topic) .load() } }
这样定义后,你可以像调用普通函数对象一样使用它,隐式参数会自动被注入:
implicit val spark: SparkSession = SparkSession.builder().master("local").getOrCreate() val myConfig = Configuration(bootstrapServers = "localhost:9092", topic = "test-topic") val df = DoSomething(myConfig) // 隐式sparkSession自动传入
方法二:使用柯里化的标准函数类型
如果一定要用标准库的函数类型,可以用柯里化的形式Configuration => SparkSession => DataFrame,但需要把隐式参数转为普通参数(内部可以标记为implicit方便使用):
import org.apache.spark.sql.{DataFrame, SparkSession} object DoSomething extends (Configuration => SparkSession => DataFrame) { override def apply(config: Configuration): SparkSession => DataFrame = { // 把返回的函数参数标记为implicit,方便内部代码使用隐式 implicit sparkSession => { val bootstrapServers = config.bootstrapServers val topic = config.topic sparkSession.readStream .format("kafka") .option("kafka.bootstrap.servers", bootstrapServers) .option("subscribe", topic) .load() } } }
调用方式略有不同,需要显式传递第二个参数(或者用implicitly获取隐式值):
implicit val spark: SparkSession = SparkSession.builder().master("local").getOrCreate() val myConfig = Configuration(bootstrapServers = "localhost:9092", topic = "test-topic") val df = DoSomething(myConfig)(spark) // 或者利用implicitly简化:val df = DoSomething(myConfig)(implicitly[SparkSession])
你原来代码的问题说明
- 函数类型写法错误:
(Configuration, ??? => Dataframe)不符合Scala函数类型的语法规则,标准函数类型是输入类型 => 输出类型,柯里化是A => B => C; - 类型不匹配:你继承的
Configuration => SparkSession和apply方法返回的DataFrame完全不兼容,这会直接导致编译失败。
内容的提问来源于stack exchange,提问作者SleepyX667
相关产品推荐
相关产品推荐

