2015-04-02 204 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