Scala 为case类合并自定义对象和编译器生成的伴生对象。合并规则是什么?
我刚刚在下面试用了这段代码,它按预期工作。它打印Scala 为case类合并自定义对象和编译器生成的伴生对象。合并规则是什么?,scala,case-class,companion-object,Scala,Case Class,Companion Object,我刚刚在下面试用了这段代码,它按预期工作。它打印1 现在,我的问题是我不明白引擎盖下面发生了什么。 一个case类如何能有两个伴生对象(一个由编译器生成,一个由我编写)?也许它不能。因此,它们必须以某种方式合并到引擎盖下。我只是不明白他们是怎么合并的?有什么特别的合并规则我应该知道吗 如果在两个伴生对象中定义的定义集是不相交的,那么生成的case类中的定义集就是两个不相交集的并集,是这样吗?我想这就是他们合并的方式,但我不确定。有人能确认这个合并规则是否是在Scala编译器中实现的规则吗?还是有
1
现在,我的问题是我不明白引擎盖下面发生了什么。
一个case类如何能有两个伴生对象(一个由编译器生成,一个由我编写)?也许它不能。因此,它们必须以某种方式合并到引擎盖下。我只是不明白他们是怎么合并的?有什么特别的合并规则我应该知道吗
如果在两个伴生对象中定义的定义集是不相交的,那么生成的case类中的定义集就是两个不相交集的并集,是这样吗?我想这就是他们合并的方式,但我不确定。有人能确认这个合并规则是否是在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类生成的伴生对象(不包括其他伴生对象): 因此,如果您声明自己的同伴对象,至少在这个简单的示例中,其效果是您的新方法被添加到同伴对象中,并且它的一些实现和功能也丢失了。如果我们试图覆盖一些剩余的自动生成的内容,看看会发生什么是很有趣的,但是剩下的不多了,所以通常不太可能引起冲突 case类的一些好处与生成的代码无关,例如使类变量公开而不必显式添加“val”关键字。下面是上面所有3个反编译示例的修改源代码 版本1(无显式伴生对象): 版本2是您的原始版本 版本3(无案例类): 在版本3中,我们需要将val添加到类A参数中(否则它们是私有的),我们必须将factory方法添加到伴随对象中,或者在创建(1,2)的实例时使用“new”关键字
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);
}
Compiled from "zip.sc"
public final class A$ {
public static final A$ MODULE$;
public static {};
public A apply(int, int);
public int A2Int(A);
}
case class A(i1:Int,i2:Int)
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
}