在Scala中,我可以使用幻像类型的概念(如here所述)来标记类型,并在运行时删除此信息。我想知道是否可以用幻像类型标记原始类型而不用它们装箱。
一个例子可以是一个函数,它允许Int只在它是素数时才通过。签名可能类似于以下内容:
def filterPrime(i: Int): Option[Int with IsPrime]
如果Some(i)
为素数或i
,则函数返回值None
。
在没有装箱原始整数的情况下,可以在Scala中实现所提出的想法吗?
答案 0 :(得分:5)
以下适用于我:
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 */
答案 1 :(得分:4)
在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))
}
}
并使用以下结果在类Test
上调用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
}
我们注意到,函数testOddity
已被编译为返回未装箱的整数。
以下文件无法编译(这也是我们想要的)。
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)
^