【问题标题】:Default value for type parameter in ScalaScala中类型参数的默认值
【发布时间】:2015-04-02 13:24:51
【问题描述】:

我不知道如何(如果有的话)在 Scala 中为 type 参数设置默认值。
目前我有一个类似的方法:

def getStage[T <: Stage](key: String): T = {
  // Do fancy stuff that returns something
}

但我想做的是提供getStage 的实现,它不为T 取值,而是使用默认值。我试图只定义另一种方法并重载参数,但这只会导致其中一种方法被另一种方法完全覆盖。如果我不清楚我想要做的是这样的事情:

def getStage[T<:Stage = Stage[_]](key: String): T = {

}

我希望我的要求很清楚。有谁知道如何实现这样的目标?

【问题讨论】:

  • getStage 将如何返回T 类型的值(假设T 可以是任何合适的类型)?大概你必须使用asInstanceOf 或类似的,这通常是不可取的。您能否详细解释一下如何调用此代码,以及您要实现的目标是什么?
  • 很可能我做错了,因为我还没有习惯 Scala 的做事方式...... getStage 方法定义的类管理一个Map[String,SyncStage] 实例变量。我打算使用匹配来确保对象属于预期的类(因此不需要asInstanceOf),否则会引发错误(它永远不会发生,因为 key 不是运行时指定的变量)。我有一个替代方案可以完全避免这一切,但我想知道这是否可能,因为我已经处于另一个类似的情况......
  • 没有默认类型参数这样的东西。可能可以解决类型约束,但最好避免这种情况。
  • @m-z 如果您使用类型类来指导参数的推断,我认为没有任何理由建议避免这种情况。当然,您可能会遇到隐式解析规则令人困惑的情况,但这通常仍然是合理的做法。

标签: scala generics


【解决方案1】:

您可以使用类型类以类型安全的方式执行此类操作。例如,假设你有这个类型类:

trait Default[A] { def apply(): A }

以及以下类型层次结构:

trait Stage
case class FooStage(foo: String) extends Stage
case class BarStage(bar: Int) extends Stage

还有一些例子:

trait LowPriorityStageInstances {
  implicit object barStageDefault extends Default[BarStage] {
    def apply() = BarStage(13)
  }
}

object Stage extends LowPriorityStageInstances {
  implicit object stageDefault extends Default[Stage] {
    def apply() = FooStage("foo")
  }
}

然后你可以这样写你的方法:

def getStage[T <: Stage: Default](key: String): T =
  implicitly[Default[T]].apply()

它的工作原理是这样的:

scala> getStage("")
res0: Stage = FooStage(foo)

scala> getStage[BarStage]("")
res1: BarStage = BarStage(13)

我认为这或多或少是你想要的。

【讨论】:

  • 谢谢。 :) Tbh 它似乎比我预期的要复杂一些,但我想我只需要更习惯于类型类的概念。
  • 是的,Scala 对类型类的编码有点冗长,但一旦你习惯了它,它并不像看起来那么复杂。
  • 很好的答案。你能分享一个链接,指向更多关于T &lt;: Stage: Default(双类型参数?)我以前从未见过的信息吗?
  • @wipman 这不是一个真正的双精度类型参数,但我同意如果您以前没有见过它,它有点神秘。最好从两部分来看:第一部分 T &lt;: Stage 称为 upper type bound - 表示类型变量 T 指的是 Stage 类型的子类型。第二部分称为context bound,它是def getStage[T &lt;: Stage](key: String)(implicit d: Default[Stage]): T =...的语法糖
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-20
  • 1970-01-01
  • 2014-04-01
  • 1970-01-01
  • 2011-09-02
  • 2016-06-15
相关资源
最近更新 更多