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.