Scala:比较泛型类的类型

时间:2012-11-28 14:42:41

标签: class scala generics types comparison

在这个问题上有很多问题,但遗憾的是似乎没有一个问题可以解决我的问题。

我写了一个通用的scala类,我们称之为

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

以及相应的对象:

object MyClass() { ... }

在MyClass中我想要定义一个行为取决于给定类型A的函数。例如,让我们假设我想要定义类型为(A,A)=>的'较小'函数。 Boolean,默认情况下返回'true',无论元素是什么,但是要返回某些类型的正确结果,如Int,Float等。

我的想法是通过以下方式将'较小'定义为类的成员:

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还包含了类的一些构造函数调用 - ,无论我如何更改代码 - 总是导致编译器对使用清单所需的信息缺乏感到愤怒。也许有一个基于清单的解决方案,但我当然还没有找到它。

注意:使用'较小'的函数只是一个例子,我想要实现这种类型的几个函数。我知道,对于这个特定的情况,我可以简单地只允许那些可比较的类型A,但这实际上不是我想要实现的。

对不起文字墙 - 我希望能够理解我的问题。

提前感谢您的回答。

修改

也许我应该更详细一点:我想要做的是实现图像编程库(主要供我个人使用)。 'MyClass'实际上是一个'Pixelmap'类,它包含A类型的“像素”数组以及某些像素处理方法。那些Pixelmaps可以是任何类型,虽然我主要使用Float和Color数据类型,有时使用Boolean作为掩码。 我需要的数据类型相关函数之一是“混合”(虽然也使用“较小”),它在类型A的两个值之间进行插值,并且例如可以用于平滑调整这种Pixelmap的大小。默认情况下,此混合函数(类型为(A,A,Float)=&gt; A)只返回第一个给定值,但对于Float,Color等类型的Pixelmaps,则需要定义适当的插值。 因此,每个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
    ...

}

虽然这确实不是一个合适的解决方案,但它似乎让我很好地解决了这个问题。

1 个答案:

答案 0 :(得分:2)

我省略了很多东西,因为如果我说实话,我仍然不完全确定你要做什么。但是这里有一个可以帮助你的解决方案。

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)
}

我们的想法是使用MyClass方法将较小的方法定义为getSmallerFunction对象下的隐式对象。从某种意义上说,它查找满足其类型边界的type-class实例,这种方法很特殊。然后我们可以去:

println(MyClass.getSmallerFunction(1, 2))

它自动知道正确的使用方法。您可以扩展此技术来处理您的Array示例。 This is a great tutorial/presentation on what type-classes are.

编辑:我刚刚意识到您想要返回一个实际的功能。就我而言,和你的一样,类型参数丢失了。但是如果在一天结束时你只想根据类型选择性地调用方法,那么我详细介绍的方法可以帮助你。