Sil*_*man 5 scala class case-class
假设定义:
case class IntegerWrapper(i : Int)
Run Code Online (Sandbox Code Playgroud)
并且处于可能创建可能具有大量IntegerWrapper实例的情况下,i=[0..N>必须做什么:
将此范围映射到一组固定的单例 [IntegerWrapper(0) .. IntegerWrapper(N)>
保留类的现有值语义IntegerWrapper(匹配,等号,哈希码,序列化)
我希望做实例共享类似于什么java.lang.Integer.我想我的问题是,如果可以在不必自己做所有事情的情况下完成.简单地定义一个apply(i : Int)不能编译的伴随对象.有什么建议?
如果你只是想避免分配,也许你想要的是一个价值类?在Scala 2.10中,如果您的IntegerWrapper类扩展AnyVal,实例通常不会被分配,而是在值本身上调用静态方法.例如:
scala> case class IntegerWrapper(val i: Int) extends AnyVal { def increment = i + 1 }
defined class IntegerWrapper
scala> object Test { IntegerWrapper(2).increment }
defined module Test
scala> :javap -verbose Test
...
public Test$();
Code:
Stack=2, Locals=1, Args_size=1
0: aload_0
1: invokespecial #13; //Method java/lang/Object."<init>":()V
4: aload_0
5: putstatic #15; //Field MODULE$:LTest$;
8: getstatic #20; //Field IntegerWrapper$.MODULE$:LIntegerWrapper$;
11: iconst_2
12: invokevirtual #24; //Method IntegerWrapper$.extension$increment:(I)I
15: pop
16: return
Run Code Online (Sandbox Code Playgroud)
请注意,那里调用的扩展方法是Int => Int.
为了比较,如果你不扩展,这是你得到的AnyVal:
scala> :javap -verbose Test
...
public Test$();
Code:
Stack=3, Locals=1, Args_size=1
0: aload_0
1: invokespecial #13; //Method java/lang/Object."<init>":()V
4: aload_0
5: putstatic #15; //Field MODULE$:LTest$;
8: new #17; //class IntegerWrapper
11: dup
12: iconst_2
13: invokespecial #20; //Method IntegerWrapper."<init>":(I)V
16: invokevirtual #24; //Method IntegerWrapper.increment:()I
19: pop
20: return
Run Code Online (Sandbox Code Playgroud)
使用此版本,您可以查看对象分配以及对新IntegerWrapper实例的方法的调用.
像这样的东西吗?
sealed trait IntegerWrapper {
def i: Int
}
object IntegerWrapper extends (Int => IntegerWrapper) {
private case class IntegerWrapperImpl(i: Int) extends IntegerWrapper
private val instances: List[IntegerWrapperImpl] = ...
/* Wrapper instances for i in [0..N) */
def apply(i: Int): IntegerWrapper = instances(i)
def unapply(iw: IntegerWrapper): Option[Int] = Some(iw.i)
}
Run Code Online (Sandbox Code Playgroud)
优点是equals和hashCode仍然由编译器生成,因为IntegerWrapperImpl是一个案例类。缺点是您不能直接使用其他编译器添加的案例类好东西,例如copy. 如果你想使用它,要么暴露IntegerWrapperImpl给客户端,或者,恕我直言,最好添加copy到IntegerWrapper接口中。
模式匹配照常工作:
val iw0 = IntegerWrapper(0)
val iw1: IntegerWrapper = IntegerWrapper(1)
iw0 match {
case IntegerWrapper(0) => println("IW(0)")
case _ => println("something else")
} // IW(0)
iw1 match {
case IntegerWrapper(1) => println("IW(1)")
case _ => println("something else")
} // IW(1)
iw1 match {
case IntegerWrapper(2) => println("IW(2)")
case _ => println("something else")
} // something else
Run Code Online (Sandbox Code Playgroud)