2013-02-16 49 views
3

似乎TypeTags只適用於在被調用方法的參數使用的類型參數的工作,而不是返回類型:爲什麼TypeTag不適用於返回類型?

scala> :paste 
// Entering paste mode (ctrl-D to finish) 

import scala.reflect.runtime.universe._ 

object Test { 
    def withParam[T: TypeTag](v: T): T = { 
    println(typeOf[T]) 
    0.asInstanceOf[T] 
    } 

    def justReturn[T: TypeTag](): T = { 
    println(typeOf[T]) 
    0.asInstanceOf[T] 
    } 
} 

// Exiting paste mode, now interpreting. 

import scala.reflect.runtime.universe._ 
defined module Test 


scala> val i: Int = Test.withParam(17) 
Int 
i: Int = 0 

scala> val j: Int = Test.justReturn() 
Nothing 
j: Int = 0 

這是清單的2.9的行爲是一致的,但沒有任何無法完成的原因,還有其他方法可以達到這個效果嗎?

+1

還有什麼可能呢?也就是說,_should_'justReturn'返回? – 2013-02-16 18:42:55

回答

2

類型系統以最嚴格的類型開始(即Nothing,其中不存在任何實例;如果存在,它將是一種能夠代表任何事物並且做任何事情的神似的價值)。然後根據需要擴大類型,但由於回報處於逆轉狀態,因此從來沒有理由加寬。如果你真的可以退回Nothing,你會在所有情況下設置。

然後,您通過告知0Nothing的實例來顛覆類型系統。這當然是完全錯誤的,但編譯器忠實地相信你,並且通過將其分配給Int來解決這種情況,這正是它一直以來的情況。 (它也會很樂意嘗試將它分配給String,然後你會在運行時得到一個異常,因爲那時它是無意義的。)

理論上這可以做不同的事情,但這是一個非常基本的部分類型推斷算法。

+1

事實上,如果您使用除「Int」之外的顯式類型參數調用原始'justReturn',則這是編譯時錯誤。有趣的是,如果您通過「弱一致性」給出了一個與「Int」兼容的顯式類型參數,則錯誤確實在運行時發生。例如,'Test.justReturn [Byte]()'引發'java.lang.ClassCastException:java.lang.Integer不能轉換爲java.lang.Byte'。 – 2013-02-16 20:19:20

+0

@RandallSchulz - 我在所有情況下都得到'ClassCastExceptions'。你使用什麼版本? (這裏是2.10.0) – 2013-02-16 20:53:32

+0

如果這是算法的工作方式,那麼這是有道理的。謝謝。 – Yan 2013-02-16 22:26:41

2

爲了擴大雷克斯克爾的評論,在justReturn案件中推動T沒有任何推論。如果更改justReturn這個

scala> val j: Int = Test.justReturn[Int]() 
Int 
j: Int = 0 

:如果您提供的(適用)類型的參數,你得到這個

def justReturn[T: TypeTag]() { 
    println(typeOf[T]) 
} 

...那麼你可以這樣做:

scala> justReturn[String]() 
String 

scala> justReturn[java.io.File]() 
java.io.File 
相關問題