1

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

我写了一个通用的 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) => 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
    ...

}

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

4

1 回答 1

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方法的 , 对象下的隐式对象。此方法的特殊之处在于它查找满足其类型界限的类型类实例。然后我们可以去:

println(MyClass.getSmallerFunction(1, 2))

它会自动知道要使用的正确方法。您可以扩展此技术来处理您的 Array 示例。这是一个关于什么是类型类的很棒的教程/演示。

编辑:我刚刚意识到您想要返回一个实际的函数。在我的情况下,和你一样,类型参数丢失了。但是,如果在一天结束时您只想能够根据类型有选择地调用方法,那么我详细介绍的方法应该对您有所帮助。

于 2012-11-28T15:13:54.453 回答