在这个问题上有很多问题,但遗憾的是似乎没有一个问题可以解决我的问题。
我写了一个通用的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
...
}
虽然这确实不是一个合适的解决方案,但它似乎让我很好地解决了这个问题。
答案 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.
编辑:我刚刚意识到您想要返回一个实际的功能。就我而言,和你的一样,类型参数丢失了。但是如果在一天结束时你只想根据类型选择性地调用方法,那么我详细介绍的方法可以帮助你。