如何在Scala中声明变量参数抽象函数

时间:2019-03-25 15:48:59

标签: scala

我试图在接受可变数量参数的trait中声明函数,并且在实现trait期间,我将扩展参数数量。如何在Scala中完成

我期望提供如下代码。

trait Column {
  def rule
}

case object FirstColumn extends Column{
 def rule(s: String) : String
}

case object SecondColumn extends Column{
 def rule(s1: String, s2: String) : String
}

我尝试使用Strings *,但是不允许我在实现过程中扩展参数数量。我知道可以使用多种方法来解决此问题,但我特别希望拥有上述签名供我的团队编写函数。

1 个答案:

答案 0 :(得分:2)

这主要是针对我对这个问题的评论。这个答案可以使您尽可能地接近Scala所需要的内容,但这也说明了为什么做自己的工作可能不是一个好主意。

您可以表达(接近)您想要的类型,但是我不确定您打算获得什么。首先,如果要采用其他arglist类型,则Column必须是通用的。

trait Column[-A] {
  def rule(arg: A): String
}

然后我们可以将您的case对象实现为对此的适当参数化的子类。

case object FirstColumn extends Column[String] {
  def rule(arg: String): String =
    "stub implementation"
}

case object SecondColumn extends Column[(String, String)] {
  def rule(arg: (String, String)): String =
    "stub implementation"
}

请注意,FirstColumnSecondColumn 不会从相同的Column[A]继承,因为它们没有实现相同的方法。我们可以使它们具有共同的类型,但是……不是一种非常有用的方式。

一个选择是找到Column[String]Column[(String, String)]的公共超类型,这(因为自变量是自变量)类似于找到String和{{1}的公共子类型。 }。最接近的常见子类型是... (String, String)。除非您仅打算将Null传递到null,否则这无济于事。

相反,我们可以使用存在性。

rule

现在,我们已经丢失了所有类型信息。您可以访问 val foo: Column[_] = FirstColumn val bar: Column[_] = SecondColumn 插槽并可以打印它,但是您不能调用它,因为我们不知道需要传递什么。您必须进行强制转换才能将其恢复为可用格式。

我在这里要说的是,是的,这是可行的,但是一旦丢失了尽可能多的类型信息,就没有什么意义了。类型系统正确地告诉我们foo.rulefoo实际上没有什么共同之处,只是名为bar的方法的 existence 存在……论据。从类型理论的角度来看,很难做到比这更有趣。