代码之家  ›  专栏  ›  技术社区  ›  waterlooalex

用构造函数参数扩展scala中的类会给类添加VAL(字段)吗?

  •  11
  • waterlooalex  · 技术社区  · 14 年前

    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)
    

    我感兴趣的是每个类的实例占用多少内存。类的实例将有一个成员变量:foo。

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

    2 回复  |  直到 14 年前
        1
  •  14
  •   Rex Kerr    14 年前

    所有编译的例子( A , B , D E )占用完全相同的存储空间。事实上,甚至

    class F(val bar: String) extends A(bar)
    

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

    class G(var bar: String) extends A(bar)
    

    然后构造一个新字段。

    您可以通过编译上面的示例并查看 javap -c Classname (注意 2: 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    
    }
    

    (以及缺少一个额外的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
    

    (又有一个在那里) 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
    
        2
  •  7
  •   Randall Schulz    14 年前

    你们班 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 }
    

    我对此感到困惑:

    % 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);
    }
    

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

    推荐文章