views:

113

answers:

1

I have

class Address(elem: scala.xml.Elem){
    val attr1 = (elem \ "attr1") text
    ...
}

I do not want elem to be a member of Address to keep the the footprint to minimum as I create few millions of such objects in memory. What is the scala way to achieve this? Thanks.

+9  A: 

You achieve it just the way you've shown. Just make sure you only refer to elem as part of the class initializer, not in other methods where it will have to be stored so it can be recalled.

Here's the bytecode for what you wrote (use javap -p ClassName on compiled classes):

public Address(scala.xml.Elem);
  Code:
   0:   aload_0
   1:   invokespecial   #18; //Method java/lang/Object."<init>":()V
   4:   aload_0
   5:   aload_1
   6:   ldc #19; //String attr1
   8:   invokevirtual   #25; //Method scala/xml/Elem.$bslash:(Ljava/lang/String;)Lscala/xml/NodeSeq;
   11:  invokevirtual   #30; //Method scala/xml/NodeSeq.text:()Ljava/lang/String;
   14:  putfield    #11; //Field attr1:Ljava/lang/String;
   17:  return

Note that there is only one putfield, namely the one to initialize the val attr1. If elem were saved inside the class, it would need its own putfield. If you change the val to a def, you get instead:

public Address(scala.xml.Elem);
  Code:
   0:   aload_0
   1:   aload_1
   2:   putfield    #12; //Field elem:Lscala/xml/Elem;
   5:   aload_0
   6:   invokespecial   #31; //Method java/lang/Object."<init>":()V
   9:   return

where you can see that the Elem has been stored so the def can use it on each invocation.

If you want the Elem to be stored and accessible, you would have to declare the class

class Address(val elem: scala.xml.Elem) { ... }

(note the val).

Only if you use a case class is the constructor argument is always stored: case classes are designed for pattern matching, and of course you need to store the argument if you're going to try to match against it later.

Rex Kerr