关于这个问题有很多问题,但遗憾的是似乎没有一个可以解决我的问题。
我写了一个通用的 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
...
}
虽然这真的不是一个合适的解决方案,但它似乎让我很好地解决了这个问题。