我刚刚尝试了下面的代码,它按预期工作.它打印1.
现在,我的问题是,我不明白幕后发生了什么.
案例类如何有两个伴随对象(一个由编译器生成,另一个由我编写)?可能它不能.所以他们必须以某种方式合并在引擎盖下.我只是不明白他们是如何合并的?我应该注意哪些特殊的合并规则?
是否如此,如果两个伴随对象中定义的定义集是不相交的,那么结果案例类中的定义集只是两个不相交集的并集?我认为这是他们合并的方式,但我不确定.有人可以确认这个合并规则是否是Scala编译器中实现的规则?或者还有什么额外的东西吗?
更具体地说,编译生成的伴随对象和我的伴随对象的规则是什么?是否在某处指定了这些规则?
我还没有真正看过我在Scala的几本书中讨论的这个话题 – 也许是表面上看起来 – 读过.
object A{
implicit def A2Int(a:A)=a.i1
}
case class A(i1:Int,i2:Int)
object Run extends App{
val a=A(1,2)
val i:Int=a
println(i)
}
最佳答案 我不知道合并自动和显式伴随对象的算法在哪里被描述或记录(除了编译器源),但是通过编译代码然后检查生成的伴随对象(使用javap),我们可以看出差异是什么是(这是scala 2.10.4).
这是为case类生成的伴随对象(没有你的附加伴随对象):
Compiled from "zip.sc"
public final class A$extends scala.runtime.AbstractFunction2<Object, Object, A> implements scala.Serializable {
public static final A$MODULE$;
public static {};
public A apply(int, int);
public scala.Option<scala.Tuple2<java.lang.Object, java.lang.Object>> unapply(A);
public java.lang.Object apply(java.lang.Object, java.lang.Object);
public final java.lang.String toString();
}
添加伴随对象后,这是生成的内容:
Compiled from "zip.sc"
public final class A$implements scala.Serializable {
public static final A$MODULE$;
public static {};
public A apply(int, int);
public scala.Option<scala.Tuple2<java.lang.Object, java.lang.Object>> unapply(A);
public int A2Int(A);
}
显式伴随对象定义导致的生成的伴随对象的差异似乎是:
>它不再扩展AbstractFunction2
>它不再具有与子弹1相关的工厂方法(申请)
>它不再覆盖toString方法(我想如果需要,你应该提供一个)
>添加了您的A2Int方法
如果case类更改为普通类(以及进行编译所需的最小更改),结果如下:
Compiled from "zip.sc"
public final class A${
public static final A$MODULE$;
public static {};
public A apply(int, int);
public int A2Int(A);
}
所以,如果你声明自己的伴随对象,至少在这个简单的例子中,效果是你的新方法被添加到伴侣对象,其中一些实现和功能也会丢失.如果我们试图覆盖一些剩余的自动生成的东西会发生什么会很有趣,但是剩下的不多,所以通常不会引起冲突.
案例类的一些好处与生成的代码无关,例如使类变量公开而不必显式添加’val’关键字.这是上面所有3个反编译示例的修改源代码.
版本1(没有明确的伴随对象):
case class A(i1:Int,i2:Int)
版本2是您的原始版本.
版本3(无案例类):
object A {
implicit def A2Int(a:A)=a.i1
def apply(a:Int,b:Int):A = new A(a,b)
}
class A(val i1:Int,val i2:Int)
object Run extends App{
import A._
val a=A(1,2)
val i:Int=a
}
在版本3中,我们需要向类A参数添加val(否则它们是私有的),我们必须将工厂方法添加到我们的伴随对象,或者在创建A的实例时使用’new’关键字(1 ,2).