Say I have:
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)
I'm interested in how much memory instances of each of these classes take up. Instances of class A will have a single member variable: foo.
How about classes B,C,D and E? How many member variables will they each have? I suspect E will have two (E.bar, A.foo), I expect D will have one (A.foo), but I wonder about B and C, might they have two? (B.foo, A.foo)?
extends: The extends keyword in Scala is used to inherit features of one class by another class. baseClass extends parentClass. This extends keyword is used to inherit class while creating a new one. With: the with keyword in Scala is used when we need to inherit more than one class by another class.
The first thing you inherit from can either be a trait or a class, using the extends keyword. You can define further inherited traits (and only traits) using the with keyword.
Extending a class in Scala user can design an inherited class. To extend a class in Scala we use extends keyword. there are two restrictions to extend a class in Scala : To override method in scala override keyword is required.
Objects and classes are not completely decoupled. An object can extend another class, making its fields and methods available in a global instance.
All of the examples that compile (A
, B
, D
, E
) take exactly the same amount of storage space. In fact, even
class F(val bar: String) extends A(bar)
will have the data stored in one field--it just gets an extra accessor method for the same field. However, if you
class G(var bar: String) extends A(bar)
then a new field is constructed.
You can check all this by compiling your examples above and looking at the bytecode from javap -c Classname
(note the putfield at 2:
in the constructor of 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
}
(And the lack of an extra putfield in 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
(And the presence of one again in 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
You class C
will require an override
keyword on val foo
to compile, rendering it identical to D
. It will store its own copy of foo. You class B
does not add storage unless someplace outside its constructor body there is a reference to foo
. That would force a hidden field to be created to hold the constructor parameter. The constructor body is all the code within the class definition and outside any method body.
Addendum:
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 }
I am perplexed by this:
% 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);
}
What is method barbar
using to get its return value?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With