问题描述
|
在Scala中,我可以使用幻像类型的概念(如此处所述)来标记类型,并在运行时删除此信息。我想知道是否有可能在不将它们装箱的情况下用幻像类型标记原始类型。
一个示例可能是一个函数,该函数仅在Int是质数时才允许Int通过。签名可能类似于以下内容:
def filterPrime(i: Int): Option[Int with IsPrime]
如果i
是素数,否则函数function3ѭ,该函数返回值Some(i)
。
所陈述的想法是否可以在Scala中实现而无需将原始整数装箱?
解决方法
以下对我有用:
trait IsPrime
val x = 5.asInstanceOf[Int with IsPrime]
val y:Int = x
val z:Int with IsPrime = 6 /* this line causes a compile error
which is what you want */
, 在Kim Stebel的答案的基础上,我编写了以下内容
trait IsOdd
object Test{
def testOddity(i: Int): Int with IsOdd =
if( i % 2 == 0) throw new RuntimeException
else i.asInstanceOf[Int with IsOdd]
def main(args: Array[String]) {
println(testOddity(1))
}
}
并在类“ 6”上调用了javap,结果如下
Compiled from \"Test.scala\"
public final class Test extends java.lang.Object{
public static final void main(java.lang.String[]);
Code:
0: getstatic #11; //Field Test$.MODULE$:LTest$;
3: aload_0
4: invokevirtual #13; //Method Test$.main:([Ljava/lang/String;)V
7: return
public static final int testOddity(int);
Code:
0: getstatic #11; //Field Test$.MODULE$:LTest$;
3: iload_0
4: invokevirtual #17; //Method Test$.testOddity:(I)I
7: ireturn
}
我们注意到,函数“ 8”已被编译为返回未装箱的整数。
而且以下文件无法编译(这也是我们想要的)。
trait IsOdd
object Test{
def testOddity(i: Int): Int with IsOdd =
if( i % 2 == 0) throw new RuntimeException
else i.asInstanceOf[Int with IsOdd]
def acceptOdd(i: Int with IsOdd) { println(\"got it\") }
def main(args: Array[String]) {
println(testOddity(1))
acceptOdd(1)
}
}
编译器错误
Test.scala:11: error: type mismatch;
found : Int(1)
required: Int with IsOdd
acceptOdd(1)
^