inheritance confusion

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Ashkon

    inheritance confusion

    Can someone please help explain the following behaviour, or point me
    to a post that explains it?

    While i was debugging one of my company's programs i noticed some
    objects behaving strangely. I was having a very difficult time
    finding the source of the problem. Finally, when i realized what was
    going on i wrote the following three classes to try to understand what
    happens in the JVM.

    Given:
    /**
    * @author Ashkon Sabet
    * www.ashkon.net
    */

    public class Parent
    {
    protected boolean parentBoolean = false;

    public Parent()
    {
    System.out.prin tln("Entering Parent() Constructor");

    init();

    System.out.prin tln("Exiting Parent() Constructor");
    }

    protected void init()
    {
    System.out.prin tln("Entering Parent.init()") ;

    parentBoolean = true;

    System.out.prin tln("Value of parentBool "+parentBoolean );

    System.out.prin tln("Exiting Parent.init()") ;
    }
    }

    /**
    * @author Ashkon Sabet
    * www.ashkon.net
    */
    public class Child extends Parent
    {
    protected boolean childBoolean = false;

    public Child()
    {
    super();
    }

    protected void init()
    {
    System.out.prin tln("Entering Child.init()");

    super.init();

    setChildBoolean ();

    System.out.prin tln("Child.chil dBoolean = "+childBoolean) ;

    System.out.prin tln("Exiting Child.init()");
    }

    public void setChildBoolean ()
    {
    if (super.parentBo olean == true)
    this.childBoole an = true;
    }
    }

    /**
    *
    * @author Ashkon Sabet
    * www.ashkon.net
    */

    public class FamilyTester {

    /** Creates a new instance of FamilyTester */
    public FamilyTester() {
    }

    /**
    * @param args the command line arguments
    */
    public static void main(String[] args) throws Exception{
    Child myFirstChild = new Child();
    System.out.prin tln("My First Child Boolean ==
    "+myFirstChild. childBoolean);

    // Child mySecondChild = new Child();
    // mySecondChild.s etChildBoolean( );
    // System.out.prin tln("My Second Child Boolean ==
    "+mySecondChild .childBoolean);

    }
    }

    When you run FamilyTester you get the following output:

    Entering Parent() Constructor
    Entering Child.init()
    Entering Parent.init()
    Value of parentBool true
    Exiting Parent.init()
    Child.childBool ean = true
    Exiting Child.init()
    Exiting Parent() Constructor
    My First Child Boolean == false

    *************** *************** *
    I would have expected the last line to read:
    My First Child Boolean == true

    Thank you for you help.
    -Ash
  • Raymond DeCampo

    #2
    Re: inheritance confusion

    Yes, I will try to explain this. Before the Child instance is
    initialized, the Parent instance within that Child instance is
    constructed. So, the Parent constructor is called, then the
    initializers for the Child class are run, then the Child constructor is
    executed. For the variable childBoolean, this is what happens:

    1) Parent constructor is run. Parent constructor calls init(), which
    results in Child.init() being executed. So childBoolean is set to true.

    2) Child initializers are executed. childBoolean is then set to false.

    3) Child constructor is executed, no change for childBoolean.

    To see this in action, try the following modification and note when the
    new message is displayed:

    class Parent
    {
    protected boolean parentBoolean = false;

    public Parent()
    {
    System.out.prin tln("Entering Parent() Constructor");

    init();

    System.out.prin tln("Exiting Parent() Constructor");
    }

    protected void init()
    {
    System.out.prin tln("Entering Parent.init()") ;

    parentBoolean = true;

    System.out.prin tln("Value of parentBool "+parentBoolean );

    System.out.prin tln("Exiting Parent.init()") ;
    }
    }

    class Child extends Parent
    {
    protected boolean childBoolean = false;
    private String msg = getMsg();

    public Child()
    {
    super();
    }

    protected void init()
    {
    System.out.prin tln("Entering Child.init()");

    super.init();

    setChildBoolean ();

    System.out.prin tln("Child.chil dBoolean = "+childBoolean) ;

    System.out.prin tln("Exiting Child.init()");
    }

    public void setChildBoolean ()
    {
    if (super.parentBo olean == true)
    this.childBoole an = true;
    }

    private String getMsg()
    {
    String result = "childBoole an was just initialized to false";
    System.out.prin tln(result);
    return result;
    }
    }

    public class FamilyTester {

    /** Creates a new instance of FamilyTester */
    public FamilyTester() {
    }

    /**
    * @param args the command line arguments
    */
    public static void main(String[] args) throws Exception{
    Child myFirstChild = new Child();
    System.out.prin tln("My First Child Boolean == "
    +myFirstChild.c hildBoolean);

    }
    }



    Ray

    Comment

    • Neomorph

      #3
      Re: inheritance confusion

      On 28 Aug 2003 23:56:26 -0700, ashkon@hotmail. com (Ashkon) two-finger
      typed:
      [color=blue]
      >Ray,
      >
      >Thank you for your insight. I understand what is happening now.
      >
      >However, the flow of the source code makes it seem more intuitive to
      >have Child's global data members created and initialized before
      >Parent's constructor is run and not in between the running of Parent's
      >constructor and Child's constructor. From your post though, i
      >understand that Parent's constructor is executed before Child's global
      >data memebers are defined.
      >
      >Thank you. You are genius! :)
      >
      >So, what now? What if i need to override Parent's init() method but
      >still call it and still set global data memeber values? What's a good
      >solution?[/color]

      Why not try this:

      public class Parent {

      protected boolean parentBoolean = false;

      public Parent() {
      Parent.init(thi s);
      }

      static void init(Parent p) {
      p.parentBoolean = true ;
      }
      }

      public class Child {

      protected boolean childBoolean = false;

      public Child() {
      super();
      Child.init(this );
      }

      static void init(Child p) {
      p.childBoolean = true ;
      }
      }

      This way the parent only ever initializes parent variables, and the child
      does the parent first, and then only its own variables.

      Cheers.

      Comment

      • Raymond DeCampo

        #4
        Re: inheritance confusion

        Ashkon wrote:[color=blue]
        > Ray,
        >
        > Thank you for your insight. I understand what is happening now.
        >
        > However, the flow of the source code makes it seem more intuitive to
        > have Child's global data members created and initialized before
        > Parent's constructor is run and not in between the running of Parent's
        > constructor and Child's constructor. From your post though, i
        > understand that Parent's constructor is executed before Child's global
        > data memebers are defined.
        >
        > Thank you. You are genius! :)
        >
        > So, what now? What if i need to override Parent's init() method but
        > still call it and still set global data memeber values? What's a good
        > solution?
        >[/color]
        Glad I could help.

        There are many ways to do what you want. I suspect that the example is
        too simplified to really understand what you need. Perhaps if you try
        to explain the context a little more.

        Ray

        Comment

        • JGod

          #5
          Re: inheritance confusion

          Good example, and I'm only taking an educated guess at what's going on here.

          I compiled your example and saw your results.

          I found that if you change this line:

          protected boolean parentBoolean = false;

          to

          protected boolean parentBoolean;

          you WILL get the result you expect ("My First Child Boolean = true").

          This tells me that fields are initialized to their DEFAULT values
          immediately upon entering the constructor but then to their declared
          initializations immediately AFTER a call to super(), if one exists (and
          which of course has to be the first line of the constructor if it were to
          exist at all).

          I can't explain the rationalization for why the JVM chooses (if it was even
          intended at all!) this behaivor, but it's clearly true.

          Btw, your example would be cleaner for explaining the point at hand if you
          changed Child to simply be:

          class Child extends Parent
          {
          protected boolean childBoolean = false;

          public Child() {
          super(); // will call Child.init()
          }

          protected void init() {
          childBoolean= true;
          }
          }

          You would see the same result: false returned as is; but true returned if
          the initialization (which appears to be harmless duplication) were removed.


          "Ashkon" <ashkon@hotmail .com> wrote in message
          news:d882372b.0 308281217.7081c [email protected] gle.com...[color=blue]
          > Can someone please help explain the following behaviour, or point me
          > to a post that explains it?
          >
          > While i was debugging one of my company's programs i noticed some
          > objects behaving strangely. I was having a very difficult time
          > finding the source of the problem. Finally, when i realized what was
          > going on i wrote the following three classes to try to understand what
          > happens in the JVM.
          >
          > Given:
          > /**
          > * @author Ashkon Sabet
          > * www.ashkon.net
          > */
          >
          > public class Parent
          > {
          > protected boolean parentBoolean = false;
          >
          > public Parent()
          > {
          > System.out.prin tln("Entering Parent() Constructor");
          >
          > init();
          >
          > System.out.prin tln("Exiting Parent() Constructor");
          > }
          >
          > protected void init()
          > {
          > System.out.prin tln("Entering Parent.init()") ;
          >
          > parentBoolean = true;
          >
          > System.out.prin tln("Value of parentBool "+parentBoolean );
          >
          > System.out.prin tln("Exiting Parent.init()") ;
          > }
          > }
          >
          > /**
          > * @author Ashkon Sabet
          > * www.ashkon.net
          > */
          > public class Child extends Parent
          > {
          > protected boolean childBoolean = false;
          >
          > public Child()
          > {
          > super();
          > }
          >
          > protected void init()
          > {
          > System.out.prin tln("Entering Child.init()");
          >
          > super.init();
          >
          > setChildBoolean ();
          >
          > System.out.prin tln("Child.chil dBoolean = "+childBoolean) ;
          >
          > System.out.prin tln("Exiting Child.init()");
          > }
          >
          > public void setChildBoolean ()
          > {
          > if (super.parentBo olean == true)
          > this.childBoole an = true;
          > }
          > }
          >
          > /**
          > *
          > * @author Ashkon Sabet
          > * www.ashkon.net
          > */
          >
          > public class FamilyTester {
          >
          > /** Creates a new instance of FamilyTester */
          > public FamilyTester() {
          > }
          >
          > /**
          > * @param args the command line arguments
          > */
          > public static void main(String[] args) throws Exception{
          > Child myFirstChild = new Child();
          > System.out.prin tln("My First Child Boolean ==
          > "+myFirstChild. childBoolean);
          >
          > // Child mySecondChild = new Child();
          > // mySecondChild.s etChildBoolean( );
          > // System.out.prin tln("My Second Child Boolean ==
          > "+mySecondChild .childBoolean);
          >
          > }
          > }
          >
          > When you run FamilyTester you get the following output:
          >
          > Entering Parent() Constructor
          > Entering Child.init()
          > Entering Parent.init()
          > Value of parentBool true
          > Exiting Parent.init()
          > Child.childBool ean = true
          > Exiting Child.init()
          > Exiting Parent() Constructor
          > My First Child Boolean == false
          >
          > *************** *************** *
          > I would have expected the last line to read:
          > My First Child Boolean == true
          >
          > Thank you for you help.
          > -Ash[/color]


          Comment

          Working...