簡體   English   中英

Scala:比較泛型類的類型

[英]Scala: compare type of generic class

關於這個問題有很多問題,但遺憾的是似乎沒有一個能解決我的問題。

我寫了一個通用的 scala 類,讓我們稱之為

class MyClass[A]() { ... }

以及相應的對象:

object MyClass() { ... }

在 MyClass 中,我想定義一個函數,其行為取決於給定的類型 A。例如,假設我想定義一個類型為 (A, A) => Boolean 的“較小”函數,默認情況下返回“true”無論元素是什么,但旨在為某些類型(如 Int、Float 等)返回正確的結果。

我的想法是通過以下方式將 'smaller' 定義為類的成員:

class MyClass[A]() {

    val someArray = new Array[A](1) // will be referred to later on

    var smaller:(A,A) => Boolean = MyClass.getSmallerFunction(this)

    ...some Stuff...

}

object MyClass {

    def getSmallerFunction[A](m:MyClass[A]):(A,A) => Boolean = { 

        var func = (a:Boolean, b:Boolean) => true

        // This doesn't compile, since the compiler doesn't know what 'A' is
        if(A == Int) func = ((a:Int, b:Int) => (a<b)).asInstanceOf[(A,A) => Boolean)]

        // This compiles, but always returns true (due to type erasure I guess?)
        if(m.isInstanceOf[MyClass[Float]]) func = ((a:Float, b:Float) => (a<b)).asInstanceOf[(A,A) => Boolean)]

        // This compiles but always returns true as well due to the newly created array only containing null-elements
        if(m.someArray(0).isInstanceOf[Long]) func = ((a:Long, b:Long) => (a<b)).asInstanceOf[(A,A) => Boolean)]

    }

    ...some more stuff...

}

getSmallerFunction 方法包含一些我嘗試過的實現,但它們都不起作用。

經過一段時間研究該主題后,起初似乎清單是要走的路,但不幸的是,由於對象 MyClass 還包含該類的一些構造函數調用,因此它們似乎在這里不起作用 - 無論我如何更改代碼 - 總是導致編譯器因為缺少使用清單所需的信息而生氣。 也許有一個基於清單的解決方案,但我當然還沒有找到。

注意:'smaller' 函數的用法只是一個例子,我想實現幾個這種類型的函數。 我知道對於這種特定情況,我可以只允許那些可比較的類型 A,但這實際上不是我想要實現的。

對不起,文字牆 - 我希望有可能理解我的問題。

預先感謝您的回答。

編輯:

也許我應該更詳細一點:我試圖做的是實現一個用於圖像編程的庫(主要供我個人使用)。 'MyClass' 實際上是一個 'Pixelmap' 類,它包含一個類型為 A 的“像素”數組以及某些像素操作方法。 這些 Pixelmaps 可以是任何類型,盡管我主要使用 Float 和 Color 數據類型,有時使用 Boolean 作為掩碼。 我需要的數據類型相關函數之一是“混合”(盡管也使用“較小”),它在類型 A 的兩個值之間進行插值,例如可用於平滑調整此類像素圖的大小。 默認情況下,此混合函數(類型為 (A,A,Float) => A)僅返回第一個給定值,但對於 Float、Color 等類型的像素圖,需要定義適當的插值。 因此,每個 Pixelmap 實例都應該在創建后立即獲得一個指向適當的“混合”函數的指針。

編輯2:

似乎我找到了解決問題的合適方法,至少對於我的具體情況。 不過,這確實更像是一種解決方法。

我只是在 MyClass 中添加了一個類型為 A 的隱式參數:

class MyClass[A]()(implicit dummy:A) { ... }

例如,當我想找出實例 m:MyClass 的類型 A 是否為“Float”時,我可以使用“m.dummy.isInstanceOf[Float]”。 為了使其真正起作用,我為 MyClass 對象添加了一組我需要的所有數據類型的預定義隱式值:

object MyClass {

    implicit val floatDummy:Float = 0.0f
    implicit val intDummy:Int = 0
    ...

}

雖然這真的不是一個合適的解決方案,但它似乎讓我很好地解決了這個問題。

我省略了一大堆東西,因為老實說,我仍然不完全確定你想要做什么。 但這里有一個可能對您有所幫助的解決方案。

trait MyClass[A] {
  def smaller: (A,A) => Boolean
}

object MyClass {
  implicit object intMyClass extends MyClass[Int] {
    def smaller = (a:Int, b:Int) => (a < b)
  }
  implicit object floatMyClass extends MyClass[Float] {
    def smaller = (a:Float, b:Float) => (a < b)
  }
  implicit object longMyClass extends MyClass[Long] {
    def smaller = (a:Long, b:Long) => (a < b)
  }

  def getSmallerFunction[T : MyClass](a: T, b: T) = implicitly[MyClass[T]].smaller(a, b)
}

這個想法是您使用getSmallerFunction方法將較小的方法定義為MyClass對象下的隱式對象。 這個方法的特殊之處在於它尋找一個滿足其類型邊界的類型實例。 然后我們可以去:

println(MyClass.getSmallerFunction(1, 2))

它會自動知道要使用的正確方法。 您可以擴展此技術來處理您的 Array 示例。 這是關於什么是類型類的一個很好的教程/演示。

編輯:我剛剛意識到您想要返回一個實際的函數。 在我的情況下,就像你的一樣,類型參數丟失了。 但是,如果在一天結束時您只想能夠根據方法的類型有選擇地調用方法,那么我詳細介紹的方法應該可以幫助您。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM