Scala,如何指定具有多个特征的函数参数?

时间:2018-10-18 08:28:47

标签: scala

我有以下一段代码,一旦您看到我的问题,我的问题就会显而易见。

trait hasId {
  def id: String
}

trait hasCount {
  def count: Int
}

case class Foo(id: String, count: Int) extends hasId with hasCount

// This is the function I want to write
def printData(data: hasId and hasCount): Unit = {
  println(data.id + ": " data.count);
}

我应该如何声明函数签名?

3 个答案:

答案 0 :(得分:3)

答案的解决方案是with关键字,其含义与您的and相同。 Terry Dactyl写的泛型是一种可能的解决方案:

def printData[T <: hasId with hasCount](data: T): Unit = {
  println(data.id + ": " + data.count)
}

另一个是使用type的{​​{1}}别名:

with

甚至直接:

type hasIdAndCount = hasId with hasCount
def printData(data: hasIdAndCount): Unit = {
  println(data.id + ": " + data.count)
}

答案 1 :(得分:2)

def hasData[T <: HasId with HasCount](data: T): Unit = ???

答案 2 :(得分:0)

我有点喜欢@TerryDactyl的答案,但这是另一种方式:

// This is the corrected function 
def printData(data: hasId with hasCount): Unit = {
 println(data.id + ": " + data.count)
}

编辑:

由于评论表明我需要解释,并且由于scastie链接不起作用,因此以下是已编译的代码,带有编译错误,希望对您有所帮助:

scala> :paste
// Entering paste mode (ctrl-D to finish)

trait hasId {
  def id: String
}

trait hasCount {
  def count: Int
}

trait Both extends hasId with hasCount

case class Foo(id: String, count: Int) extends Both
case class Bar(id: String, count: Int) extends hasId with hasCount
case class Baz(id: String, count: Int) extends Both



def printData(data: hasId with hasCount): Unit = {
 println(data.id + ": " + data.count)
}


def printDataT[T <: hasId with hasCount](data: T): Unit = {
 println(data.id + ": " + data.count)
}


val s = Seq(Foo("idFoo", 1), Bar("idBar", 2))

val fooss = Seq(Foo("idFoo", 1), Foo("idFoo2", 2))
val boths = Seq(Foo("idFoo", 1), Baz("idBaz2", 2))


s.foreach(printData)
fooss.foreach(printData)
boths.foreach(printData)

fooss.foreach(printDataT[Foo])
fooss.foreach(printDataT[Both])
boths.foreach(printDataT[Both])
boths.foreach(printDataT[Foo])

s.foreach(printDataT[hasId with hasCount])
s.foreach(printDataT[Both])
s.foreach(printDataT[Foo])




// Exiting paste mode, now interpreting.

<console>:54: error: type mismatch;
 found   : Foo => Unit
 required: Product with Serializable with hasId with hasCount => ?
              s.foreach(printDataT[Foo])
                                  ^
<console>:48: error: type mismatch;
 found   : Foo => Unit
 required: Both with Product with Serializable => ?
              boths.foreach(printDataT[Foo])
                                      ^
<console>:51: error: type mismatch;
 found   : Both => Unit
 required: Product with Serializable with hasId with hasCount => ?
              s.foreach(printDataT[Both])
                                  ^