October 22, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

Inside Constructors

  • July 15, 2005
  • By Matt Weisfeld
  • Send Email »
  • More Articles »

Constructors and Inheritance

One of the more interesting issues that you can cover regarding construction is the order of events that occur when inheritance is used in the design. You may have noticed in the earlier examples that you were instantiating an actual Shape object. Generally, Shape would be designed as an abstract class. You then would create a concrete class, such as Circle, to inherit from Shape. This has been implemented in the code presented in Listing 5. Note that in this revised design, you must instantiate a Circle, not a Shape.

Listing 5

//Class TestShape
public class TestShape {
   public static void main (String args[]){
   Circle s = new Circle();
   }
}
// Class Shape
public abstract class Shape {
   public Shape () {
      System.out.println("Inside Shape Constructor.");
   }
}
// Class Circle
public class Circle extends Shape{
   public Circle () {
      System.out.println("Inside Circle Constructor.");
   }
}

An obvious question here is how many constructors actually exist? If this does not seem like an obvious question, you can explore this point.

Remember that, in this application, only a Circle is actually instantiated.

Circle s = new Circle();
A Shape is never instantiated—in fact it can't be, because it is abstract. Because Circle extends Shape, it inherits everything that Shape contains. Thus, if Shape contains an attribute called color, Circle inherits it. However, does Circle inherit Shape constructor? You can run the code and see whether the output from the Shape constructor is printed—see Figure 5.



Click here for a larger image.

Figure 5

As you can see, Shape's constructor is actually called when the application is run. In fact, Circle contains is own constructor that calls its parent—which in this case is, of course, Shape. Shape's constructor is called first even though a Shape class is never actually instantiated. It is interesting to look at the decompiled code from Circle using  javap seen in Figure 6—using the following invocation:

javap -c Circle



Click here for a larger image.

Figure 6

The output in Figure 6 shows information about the bytecodes that make up the Circle.class file. You can see that in the Method Circle (Circle's constructor), line 1 contains the call to the Method Shape (Shape's constructor). This is done before any code in Circle's constructor is executed. This confirms the rules that were presented in the previous column in this series.

You can mimic the default code by inserting the super() method in Circle's constructor, as indicated in Listing 6.

Listing 6

// Class Circle
public class Circle extends Shape{
   public Circle () {
      super();    // invoke the parent's constructor
      System.out.println("Inside Circle Constructor.");
   }}

When dealing with the default constructors, placing super() in the code does not provide any real functionality. However, when using designs with multiple constructors, using super() does come into play. You will explore this issue in the next article in the series.

One interesting question that you can investigate is what if you want the call to super() to occur after some other code in the constructor? In other words, does super() have to be first? As always, you can see what the compiler says.



Click here for a larger image.

Figure 7

According to the compiler, the call to super() must be the first statement in the constructor. As a review, let me cover the rules for the flow of events when using constructors in an inheritance situation.

After the new keyword is encountered and the object is allocated, the following steps occur:

  1. The first thing that happens inside the constructor is that the constructor of the class's superclass is called.
  2. Then, each class attribute of the object is initialized. These are the attributes that are part of the class definition (instance variables), not the attributes inside the constructor or any other method (local variables).
  3. Finally, the rest of the code in the constructor executes.

Conclusion

This article continued a discussion focusing on the topic of constructing objects. You covered some of the technical aspects of actually using constructors. Constructing objects properly is a very important object-oriented responsibility. It is very useful to take a look inside the bytecodes of classes to see exactly how the objects behave. Next month, you will further explore how the bytecodes are affected by overloading constructors.

References

  • Gilbert, Stephen, and Bill McCarty: Object-Oriented Design in Java. The Waite Group, 1998.
  • Meyers, Scott: Effective C++. Addison-Wesley, 1992.
  • Tyma, Paul, Gabriel Torok, and Troy Downing: Java Primer Plus. The Waite Group, 1996.
  • Ambler, Scott: The Object Primer. Cambridge University Press, 1998.
  • Jaworski, Jamie: Java 1.1 Developers Guide. Sams Publishing, 1997.

About the Author

Matt Weisfeld is a faculty member at Cuyahoga Community College (Tri-C) in Cleveland, Ohio. Matt is a member of the Information Technology department, teaching programming languages such as C++, Java, and C# .NET as well as various web technologies. Prior to joining Tri-C, Matt spent 20 years in the information technology industry gaining experience in software development, project management, business development, corporate training, and part-time teaching. Matt holds an MS in computer science and an MBA in project management. Besides the first edition of The Object-Oriented Thought Process, Matt has published two other computer books, and more than a dozen articles in magazines and journals such as Dr. Dobb's Journal, The C/C++ Users Journal, Software Development Magazine, Java Report, and the international journal Project Management. Matt has presented at conferences throughout the United States and Canada.



Page 2 of 2



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel