scala通用方法无模板

scala通用方法无模板,scala,generics,Scala,Generics,如何防止scala中泛型方法的代码重复?我的代码仅在类型参数绑定到trait而不是方法时编译 如您所见,我当前重复了传递给trait和method的类型参数 trait MyTrait[T <: Product, C <: OtherTrait] { def provide(spark: SparkSession, c: C): Dataset[T] } object ConcreteProvider extends MyTrait[MyCaseClass, MyCase

如何防止scala中泛型方法的代码重复?我的代码仅在类型参数绑定到trait而不是方法时编译

如您所见,我当前重复了传递给trait和method的类型参数

trait MyTrait[T <: Product, C <: OtherTrait] {

  def provide(spark: SparkSession, c: C): Dataset[T]
}

object ConcreteProvider
  extends MyTrait[MyCaseClass, MyCaseClassConfiguration] {
    override def provide(
        spark: SparkSession,
        c: MyCaseClassConfiguration): Dataset[MyCaseClass] = {
        spark.sql(s"SELECT field1, field2 FROM ${c.mydb}.${c.mytable}")
          .as[MyCaseClass]
    }
  }

trait-MyTrait[T一般来说,Scala不会为方法推断类型参数。但是,在您的例子中,您实际上可以使用(相当简洁的)lambda语法,因为您的示例中的
MyTrait
是“SAM”(单一抽象方法)类型:

现在可以很好地推断参数类型

注意事项:

  • ConcreteProvider
    现在是
    val
    而不是
    对象
    。对于许多(大多数?)目的来说,这并不重要
  • 这不能在顶层定义,因此您可能必须将其放入
    包对象中
  • 如果将另一个抽象方法添加到
    MyTrait
    ,此操作将失败

您仍然需要绑定
MyCaseClass
MyCaseClassConfiguration
CellFeedSubscriberConfiguration
,因此我不确定您关心的是什么样的重复。您没有显示
c
参数在
提供()
。你应该能够将
provide
的主体分解成
provideHelper
,并在trait中定义
provide
。我编辑了这个示例来展示
c
的用法。你说我还需要绑定是什么意思?我想在
[T]中引用我的类型参数
应该没问题?确实如此。重命名还需要注意,您的代码可能容易受到SQL注入的攻击。您可能应该使用更高级别的SQL API。对于Spark,请参阅:另一个警告是2.12没有Spark,2.11也需要IIRC标记
-xeexperimental
val ConcreteProvider: MyTrait[MyCaseClass, MyCaseClassConfiguration] =
    (spark, c) => spark.sql("SELECT ...").as[MyCaseClass]