Quantcast

Object initialization order in Scala

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Object initialization order in Scala

toivo-2
Hi,

Simple scala code:

class Calc( val intr: Double)

generates:

// Compiled from Simple.scala (version 1.5 : 49.0, super bit)
public class lifecalc.math2.Calc implements scala.ScalaObject {
 
  // Field descriptor #4 D
  private final double intr;
 
  // Method descriptor #6 (D)V
  // Stack: 3, Locals: 3
  public Calc(double intr);
     0  aload_0 [this]
     1  dload_1 [intr]
     2  putfield lifecalc.math2.Calc.intr : double [12]
     5  aload_0 [this]
     6  invokespecial java.lang.Object() [17]
     9  return
      Line numbers:
        [pc: 0, line: 3]
      Local variable table:
        [pc: 0, pc: 10] local: this index: 0 type: lifecalc.math2.Calc
        [pc: 0, pc: 10] local: intr index: 1 type: double
. . .

As far I understand super() must be called first, but in bytecode

          2  putfield lifecalc.math2.Calc.intr : double [12]

is executed first and super() invoked later
         6  invokespecial java.lang.Object() [17]

Java code
public class Calc {

        private final double intr;

        public Calc(double intr) {
                this.intr = intr;
        }
}

generates:

// Compiled from Calc.java (version 1.5 : 49.0, super bit)
public class jalab.Calc {
 
  // Field descriptor #6 D
  private final double intr;
 
  // Method descriptor #8 (D)V
  // Stack: 3, Locals: 3
  public Calc(double intr);
     0  aload_0 [this]
     1  invokespecial java.lang.Object() [13]
     4  aload_0 [this]
     5  dload_1 [intr]
     6  putfield jalab.Calc.intr : double [15]
     9  return
      Line numbers:
        [pc: 0, line: 7]
        [pc: 4, line: 8]
        [pc: 9, line: 9]
      Local variable table:
        [pc: 0, pc: 10] local: this index: 0 type: jalab.Calc
        [pc: 0, pc: 10] local: intr index: 1 type: double
}

Scala code works but AspectJ throws error:
Exception in thread "main" java.lang.VerifyError: (class: lifecalc/math2/Calc, method: <init> signature: (D)V) Expecting to find object/array on stack
        at lifecalc.math2.Simple$.main_aroundBody2(Simple.scala:8)
        at lifecalc.math2.Simple$$AjcClosure3.run(Simple.scala:1)
        at org.aspectj.runtime.reflect.JoinPointImpl.proceed(JoinPointImpl.java:101)

May be Scala initialization order is worng?
I am using Eclipse 3.2.2 and Scala plugin 2.7.1.r15152-b20080522020257

Cheers,
toivo

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [scala] Object initialization order in Scala

David MacIver
No, this behaviour is valid. You can assign to fields in the current
class before invoking a superconstructor. If AspectJ is getting
confused by it, that's a bug in AspectJ.

From the Java Virtual Machine Specification (
http://java.sun.com/docs/books/jvms/second_edition/html/Concepts.doc.html
):

Each instance initialization method (ยง3.9), except for the instance
initialization method derived from the constructor of class Object,
must call either another instance initialization method of this or an
instance initialization method of its direct superclass super before
its instance members are accessed. However, instance fields of this
that are declared in the current class may be assigned before calling
any instance initialization method.

On Fri, Aug 22, 2008 at 11:40 AM, toivo <[hidden email]> wrote:

>
> Hi,
>
> Simple scala code:
>
> class Calc( val intr: Double)
>
> generates:
>
> // Compiled from Simple.scala (version 1.5 : 49.0, super bit)
> public class lifecalc.math2.Calc implements scala.ScalaObject {
>
>  // Field descriptor #4 D
>  private final double intr;
>
>  // Method descriptor #6 (D)V
>  // Stack: 3, Locals: 3
>  public Calc(double intr);
>     0  aload_0 [this]
>     1  dload_1 [intr]
>     2  putfield lifecalc.math2.Calc.intr : double [12]
>     5  aload_0 [this]
>     6  invokespecial java.lang.Object() [17]
>     9  return
>      Line numbers:
>        [pc: 0, line: 3]
>      Local variable table:
>        [pc: 0, pc: 10] local: this index: 0 type: lifecalc.math2.Calc
>        [pc: 0, pc: 10] local: intr index: 1 type: double
> . . .
>
> As far I understand super() must be called first, but in bytecode
>
>          2  putfield lifecalc.math2.Calc.intr : double [12]
>
> is executed first and super() invoked later
>         6  invokespecial java.lang.Object() [17]
>
> Java code
> public class Calc {
>
>        private final double intr;
>
>        public Calc(double intr) {
>                this.intr = intr;
>        }
> }
>
> generates:
>
> // Compiled from Calc.java (version 1.5 : 49.0, super bit)
> public class jalab.Calc {
>
>  // Field descriptor #6 D
>  private final double intr;
>
>  // Method descriptor #8 (D)V
>  // Stack: 3, Locals: 3
>  public Calc(double intr);
>     0  aload_0 [this]
>     1  invokespecial java.lang.Object() [13]
>     4  aload_0 [this]
>     5  dload_1 [intr]
>     6  putfield jalab.Calc.intr : double [15]
>     9  return
>      Line numbers:
>        [pc: 0, line: 7]
>        [pc: 4, line: 8]
>        [pc: 9, line: 9]
>      Local variable table:
>        [pc: 0, pc: 10] local: this index: 0 type: jalab.Calc
>        [pc: 0, pc: 10] local: intr index: 1 type: double
> }
>
> Scala code works but AspectJ throws error:
> Exception in thread "main" java.lang.VerifyError: (class:
> lifecalc/math2/Calc, method: <init> signature: (D)V) Expecting to find
> object/array on stack
>        at lifecalc.math2.Simple$.main_aroundBody2(Simple.scala:8)
>        at lifecalc.math2.Simple$$AjcClosure3.run(Simple.scala:1)
>        at
> org.aspectj.runtime.reflect.JoinPointImpl.proceed(JoinPointImpl.java:101)
>
> May be Scala initialization order is worng?
> I am using Eclipse 3.2.2 and Scala plugin 2.7.1.r15152-b20080522020257
>
> Cheers,
> toivo
>
>
> --
> View this message in context: http://www.nabble.com/Object-initialization-order-in-Scala-tp19104940p19104940.html
> Sent from the Scala mailing list archive at Nabble.com.
>
>
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

[scala] Re: Object initialization order in Scala

Geoffrey Alan Washburn-4
In reply to this post by toivo-2
toivo wrote:

> May be Scala initialization order is worng?

No, that is the correct initialization order.  Constructor arguments
will be initialized before the object is initialized.

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [scala] Object initialization order in Scala

Lauri Alanko
In reply to this post by toivo-2
On Fri, Aug 22, 2008 at 03:40:06AM -0700, toivo wrote:
> class Calc( val intr: Double)

>   public Calc(double intr);
>      0  aload_0 [this]
>      1  dload_1 [intr]
>      2  putfield lifecalc.math2.Calc.intr : double [12]
>      5  aload_0 [this]
>      6  invokespecial java.lang.Object() [17]
>      9  return

> May be Scala initialization order is worng?

As already explained, the order is intentional. Here's some motivation
for it: instead of writing

abstract class A(i : Int) { ... initialize using i ... }
abstract class B(i : Int) extends A(i) { ... }
class C(i : Int) extends B(i) { ... }

you can write

abstract class A { val i : Int; ... initialize using i ... }
abstract class B extends A { ... }
class C(val i : Int) extends B

Since the constructor of C initializes the field i before calling the
superclass constructor, the constructor of A can use i during normal
initialization. This is also what early definitions are used for.

An advantage, in addition to the neater syntax (no need to relay the
constructor arguments all the way to the base class), is that the
latter style also works with traits and multiple inheritance, whereas
constructors can only be used with true classes.

(Btw, is there some established nomenclature: what do you call
non-trait classes, and what do you call traits and non-trait classes
together?)

Personally, I never use constructor parameters, precisely because of
their inflexibility. Instead, I use abstract value members which are
defined during object creation. Or, if a level of abstraction is
required, I use factory methods in the companion object.


Lauri
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [scala] Object initialization order in Scala

James Iry-2
I think the SLS uses the term "template" to cover the definition of classes traits and objects.  I wouldn't call it established nomenclature though, and programmers are likely to think of some kind of text/html templating system, a macro system like Template Haskell, or C++ templates if you just drop it casually into conversation.

5.1 Templates

Syntax:
   ClassTemplate ::= [EarlyDefs] ClassParents [TemplateBody]
   TraitTemplate ::= [EarlyDefs] TraitParents [TemplateBody]
   ClassParents ::= Constr {'with' AnnotType}
   TraitParents ::= AnnotType {'with' AnnotType}
   TemplateBody ::= [nl] '{' [SelfType] TemplateStat {semi TemplateStat} '}'
   SelfType ::= id [':' Type] '=>'
   | this ':' Type '=>'

A template defines the type signature, behavior and initial state of a trait
or class of objects or of a single object.


On Fri, Aug 22, 2008 at 4:35 AM, Lauri Alanko <[hidden email]> wrote:

(Btw, is there some established nomenclature: what do you call
non-trait classes, and what do you call traits and non-trait classes
together?)


Loading...