使用构造函数params在scala中扩展一个类会在类中添加vals(字段)吗?

Ale*_*ack 11 inheritance scala

说我有:

class A(val foo: String)

class B(foo: String) extends A(foo)
class C(val foo: String) extends A(foo)
class D(override val foo: String) extends A(foo)
class E(bar: String) extends A(bar)
Run Code Online (Sandbox Code Playgroud)

我对每个类的内存实例占用多少感兴趣.A类的实例将具有单个成员变量:foo.

B,C,D和E班怎么样?他们各有几个成员变量?我怀疑E会有两个(E.bar,A.foo),我希望D会有一个(A.foo),但我想知道B和C,他们可能有两个吗?(B.foo,A.foo)?

Rex*_*err 14

所有这一切都编译的例子(A,B,D,E)取准确的存储空间相同的量.事实上,甚至

class F(val bar: String) extends A(bar)
Run Code Online (Sandbox Code Playgroud)

将数据存储在一个字段中 - 它只是为同一个字段获取一个额外的存取方法.但是,如果你

class G(var bar: String) extends A(bar)
Run Code Online (Sandbox Code Playgroud)

然后构建一个新的领域.

您可以通过编译上面的示例并查看字节码来检查所有这些javap -c Classname(请注意2:构造函数中的putfield A):

public class Sizes$A extends java.lang.Object implements scala.ScalaObject{
public java.lang.String foo();
  Code:
   0:   aload_0
   1:   getfield    #11; //Field foo:Ljava/lang/String;
   4:   areturn

public Sizes$A(java.lang.String);
  Code:
   0:   aload_0
   1:   aload_1
   2:   putfield    #11; //Field foo:Ljava/lang/String;
   5:   aload_0
   6:   invokespecial   #18; //Method java/lang/Object."<init>":()V
   9:   return    
}
Run Code Online (Sandbox Code Playgroud)

(并且缺少额外的putfield F...)

public Sizes$F(java.lang.String);
  Code:
   0:   aload_0
   1:   aload_1
   2:   invokespecial   #15; //Method Sizes$A."<init>":(Ljava/lang/String;)V
   5:   return
Run Code Online (Sandbox Code Playgroud)

(再次出现一个G...)

public Sizes$G(java.lang.String);
  Code:
   0:   aload_0
   1:   aload_1
   2:   putfield    #11; //Field bar:Ljava/lang/String;
   5:   aload_0
   6:   aload_1
   7:   invokespecial   #18; //Method Sizes$A."<init>":(Ljava/lang/String;)V
   10:  return
Run Code Online (Sandbox Code Playgroud)


Ran*_*ulz 7

您的类C将需要一个override关键字val foo来编译,使其与之相同D.它将存储自己的foo副本.你的类B不会添加存储,除非它的构造函数体之外的某个地方有一个引用foo.这将强制创建隐藏字段以保存构造函数参数.构造函数体是类定义中的所有代码,并且在任何方法体之外.

附录:

package storage

    class A(val foo: String)

    class B(             foo: String) extends A(foo)
//  class C(         val foo: String) extends A(foo)
    class D(override val foo: String) extends A(foo)
    class E(             bar: String) extends A(bar)
    class F(             bar: String) extends A(bar) { def barbar: String = bar }
Run Code Online (Sandbox Code Playgroud)

我为此感到困惑:

% javap -private storage.F
Compiled from "Storage.scala"
public class storage.F extends storage.A implements scala.ScalaObject{
    public java.lang.String barbar();
    public storage.F(java.lang.String);
}
Run Code Online (Sandbox Code Playgroud)

什么是barbar用于获取其返回值的方法?