2015-04-02 100 views
12

我无法弄清楚如何(如果有的话),您可以为类型-Scala中的参数设置默认值。
目前我有一个类似的方法:Scala中类型参数的默认值

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

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

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

} 

我希望我很清楚我在问什么。有谁知道这样的事情可以实现吗?

+2

'getStage'如何返回'T'类型的值(因为'T'可以是任何适合的类型)?大概你不得不使用'asInstanceOf'或类似的东西,这通常是不可取的。你能否更详细地解释一下这个代码是如何被调用的,以及你想要实现的是什么? – DNA 2015-04-02 14:11:06

+0

很可能我做的事情完全错误,因为我还没有变得习惯于Scala的做法...... getStage方法定义的类管理着一个Map [String,SyncStage] '实例变量。我打算使用匹配来确保对象是预期的类(因此不需要'asInstanceOf'),否则会引发错误(因为键不是运行时指定的变量,所以不会发生这种情况)。我有另一种方法可以一起避免这一切,但我想知道是否有可能,因为我已经处于另一种类似的情况...... – evotopid 2015-04-02 14:19:11

+3

有没有这样的事情作为默认的类型参数。有可能解决类型约束问题,但避免这种情况可能会更好。 – 2015-04-02 14:29:03

回答

21

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

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) 

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

+1

谢谢。 :) Tbh似乎比我预期的要复杂一些,但我想我只需要更多地习惯类型类的概念。 – evotopid 2015-04-02 18:33:48

+0

是的,斯卡拉的类型类编码是一种冗长的,但一旦你习惯了它,它不像它看起来那么复杂。 – 2015-04-02 19:01:01

+1

很棒的回答。你会分享一个关于'T <:Stage:Default'(double type参数?)的更多信息的链接,我以前从未见过吗? – wipman 2017-01-25 08:32:46