2013-07-22 194 views
5

我相信一個泛型類可能會讓它的一個方法可用,只能假設它的類型參數符合一些額外的限制,比如(語法上即時修改的語法):有限類型參數的Scala泛型類的條件方法

trait Col[T] extends Traversable[T] { 
    def sum[T<:Int] :T = (0/:this)(_+_) 
} 

我想我可以使用隱式參數作爲證據...是否有語言功能?

回答

3

在這種情況下,您只能使用隱式參數,因爲類型在方法調用之前確定。

trait Col[T] extends Traversable[T] { 
    def sum(implicit num: Numeric[T]) :T = ??? 
} 

如果您呼叫將是參數的方法,你可以使用上下文的邊界,這是綁定到類型參數的隱含參數,只是語法糖:

def foo[A](implicit ev: Something[A]) = ??? 

相當於

def foo[A : Something] = ??? 
+0

謝謝,我不知道,[T:證據]是一般符號,我只用TypeTags來使用它。我如何通過這種方式訪問​​實際的隱式參數?此外,不會聲明'def sum [T:Numeric]'陰影特徵類型參數T? – Turin

+0

當你使用其他方法期望在主體中具有這種類型的參數時,通常使用這種表示法,但是你也可以通過調用隱式地[Something [A]]來得到它。對於某些類型,甚至可能有getter,比如'ClassTag',有'scala.reflect.classTag [A]',它隱式接受'ClassTag'實例並返回它。你也可以創建你自己的方法或者將這種方法應用到你隱式傳入的類型的伴侶中。 – drexin

+0

Thx,我會和它一起玩。 – Turin

7

對於類型參數,您也可以使用類型綁定的,該類型參數由隱式參數執行:

trait Col[T] extends Traversable[T] { 
    def sum(implicit ev: T <:< Int) :T = (0/:this)(_+_) 
} 

<:<實際上是一類,表示在中間符號,在Predef.scala定義,並在很多地方解釋,包括here

<:<的意思是「必須的一個亞型」

您還可以使用=:='必須等於'和X <%< Y'必須可視爲'(即。存在從Y到X的隱式轉換)

有關類型約束的更詳細說明,請參見this SO question

1

有涉及隱類的另一種選擇轉換

trait Col[T] extends Traversable[T] 

implicit class ColInt[T <: Int](val v : Col[T]) extends AnyVal { 
    def sum : T = (0 /: v)(_ + _) 
} 

在這種情況下,你不需要空特質上校了,所以你可以把它進一步comprimize這樣:

implicit class ColInt[T <: Int](val v : Traversable[T]) extends AnyVal { 
    def sum : T = (0 /: v)(_ + _) 
} 

的這種方法的好處是,它告訴編譯器,類型T實際上是Int的一個子類型,因此List[T] <: List[Int]在此上下文中仍然有效,並且不需要添加顯式轉換。隱含參數補充說,不會對List[T]工作的隱式轉換,因爲它只介紹從TInt的隱式轉換,而不是從List[T]List[Int]