2013-07-27 31 views
4


我坐在一個約10000 LoC的項目前面。我必須將這個項目從Scala 2.9更新到2.10。這樣做很好,但由於清單,我得到了許多棄用警告。

使用了stackoverflow和許多其他網站的搜索功能後,我沒有太多的問題。我想總結一下;關鍵點是:更新到Scala時的清單/類型標籤問題2.10

  1. TypeTags和ClassTags比Manifests和ClassManifest好得多。特別是可以使用這些作爲同義詞(類型標籤< - >艙單及ClassTags < - > ClassManifest)

  2. 類型標籤更強大比ClassTags,分別ClassTags是更受限制的類型標籤。 我的第一個問題:在這個項目中,經常使用方法manifest[T].erasure.getSimpleName。現在我不僅可以將其切換到typeTag[T].runtimeClass.getSimpleName,因爲代碼不會編譯,但是會編譯爲classTag[T].runtimeClass.getSimpleName這會影響語義嗎?(注:該方法erasure也已過時,你必須使用runtimeClass代替)

  3. 第二個問題:在斯卡拉2.9清單的類型檢查是那種:manifest[T] <:< manifest[A]。在Scala 2.10中,我會寫這個typeOf[T] <:< typeOf[A]。但<:<已棄用?

  4. 我可以將TypeTag轉換爲ClassTag嗎? I.e .:如果我只使用清單進行類型檢查(Nr。3)和名稱抽取(Nr。2):我能否將每個Manifest/ClassManifest重命名爲ClassTag?

回答

5
  1. 是的,你大多有等價TypeTag <-> ManifestClassTag <-> ClassManifest。除了那些過去由Manifest處理過的東西沒有直接的等價物,因爲這些操作被深入到了反射API中,就像Manifest對象上的工廠方法一樣。

  2. ClassTag現在基本上只用於獲取運行時(已擦除)類的東西。它的主要用途是創建數組,但您可以將其用於其他目的而不會出現問題。所以是的,classTag[T].runtimeClass是新的manifest[T].erasure並且完全等同於它。

  3. 這是改變最多的地方。 2.10介紹了new reflection API,當你想回答關於類型的特定問題時,你應該使用它(例如「do A <:< B?」)。並且反射API的入口點是...它的TypeTag

    假設AT的類型標籤在範圍內,新的manifest[T] <:< manifest[A]確實是typeOf[T] <:< typeOf[A]。這裏不推薦使用<:<的方法,see the scaladoc。然而,<:<ClassTag已過時,因爲ClassManifest曾經有一個,而ClassTag是新的ClassManifest

    請參閱反射指南的Common Operations on Types部分以及SO問題What is a TypeTag and how do I use it

  4. 我不認爲有一個直接的方式去從TypeTagClassTag。想想這樣說:

    • ,如果你需要的子類型或類型平等檢查,你不能使用ClassTag,你需要一個TypeTag;

    • 如果您還需要該類型的名稱,則可以從TypeTagtypeOf[T].typeSymbol.name.decoded中獲得該名稱。這會給你擦除的名字,就像你用來獲得的類名(ListList[Int]MapMap[String, Int])。這與獲取實際Class的名稱略有不同。如果您需要完整的刪除名稱(List[Int]),則typeOf[T].normalize.toString就足夠了。

    • ,如果你也絕對需要一個Class實例,或者一個真正的類名,你可以繞過與反思以後加載, 我想你別無選擇,只能問一個 ClassTag太..

      編輯:我剛剛發現this SO question,所以是的,可以從TypeTag得到ClassTag。這真是令人傷心,因爲反射庫中沒有幫助器方法。

      編輯2:根據要求,這裏是如何轉換TypeTagClassTag

      import reflect.runtime.universe._ 
      import reflect.ClassTag 
      
      def classTag2[T: TypeTag]: ClassTag[T] = { 
          ClassTag[T](typeTag[T].mirror.runtimeClass(typeTag[T].tpe)) 
      } 
      
      // example: 
      
      def doSomething[T : TypeTag] = { 
          val c = classTag2[T] 
          c.runtimeClass.getName 
      } 
      
+0

我得到了另外一個問題:我如何可以重寫'i.erasure'其中i是一個隱式的清單[T] – funnyF

+0

你應該用一個隱式的'ClassTag [T]'替換隱式的'Manifest [T]'並調用'i.runtimeClass'。 – gourlaysama

+0

謝謝,一切都是固定免除的一件事:在一種方法中,我有一個'TypeTag T',但我需要吊墜'manifest [T] .erasure'。通常情況下,我會使用'classTag [T] .runtimeClass',但是這次我不想重命名'TypeTag'到'ClassTag'(因爲這個方法是一個apply函數,很多方法調用這個apply函數) – funnyF