Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 为case类合并自定义对象和编译器生成的伴生对象。合并规则是什么?_Scala_Case Class_Companion Object - Fatal编程技术网

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
}