Docstoc

Constructors

Document Sample
Constructors Powered By Docstoc
					Constructors
When you create a new instance (a new object) of a class using the new keyword, a constructor for
that class is called. Constructors are used to initialize the instance variables (fields) of an object.
Constructors are similar to methods, but with some important differences.
       Constructor name is class name. A constructors must have the same name as the class its
        in.
       Default constructor. If you don't define a constructor for a class, a default parameterless
        constructor is automatically created by the compiler. The default constructor calls the default
        parent constructor (super()) and initializes all instance variables to default value (zero for
        numeric types, null for object references, and false for booleans).
       Default constructor is created only if there are no constructors. If you
        define any constructor for your class, no default constructor is automatically created.
       Differences between methods and constructors.
            o    There is no return type given in a constructor signature (header). The value is this
                 object itself so there is no need to indicate a return value.
            o    There is no return statement in the body of the constructor.
            o    The first line of a constructor must either be a call on another constructor in the same
                 class (usingthis), or a call on the superclass constructor (using super). If the first line
                 is neither of these, the compiler automatically inserts a call to the parameterless super
                 class constructor.

        These differences in syntax between a constructor and method are sometimes hard to see
        when looking at the source. It would have been better to have had a keyword to clearly mark
        constructors as some languages do.
       this(...) - Calls another constructor in same class. Often a constructor with few
        parameters will call a constructor with more parameters, giving default values for the missing
        parameters. Use this to call other constructors in the same class.

       super(...). Use super to call a constructor in a parent class. Calling the constructor for the
        superclass must be the first statement in the body of a constructor. If you are satisfied with
        the default constructor in the superclass, there is no need to make a call to it because it will
        be supplied automatically.


Example of explicit this constructor call

  public class Point {
        int m_x;
        int m_y;


        //============ Constructor
        public Point(int x, int y) {
                m_x = x;
                m_y = y;
        }
        //============ Parameterless default constructor
        public Point() {
              this(0, 0);       // Calls other constructor.
        }
        . . .
  }


super(...) - The superclass (parent) constructor

An object has the fields of its own class plus all fields of its parent class, grandparent class, all the way
up to the root class Object. It's necessary to initialize all fields, therefore all constructors must be
called! The Java compiler automatically inserts the necessary constructor calls in the process
of constructor chaining, or you can do it explicitly.
The Java compiler inserts a call to the parent constructor (super) if you don't have a constructor call
as the first statement of you constructor. The following is the equivalent of the constuctor above.
        //============ Constructor (same as in above example)
        public Point(int x, int y) {
              super();      // Automatically done if you don't call constructor here.
              m_x = x;
              m_y = y;
        }


Why you might want to call super explicitly

Normally, you won't need to call the constructor for your parent class because it's automatically
generated, but there are two cases where this is necessary.
    1. You want to call a parent constructor which has parameters (the automatically
       generated superconstructor call has no parameters).
    2. There is no parameterless parent constructor because only constructors with parameters are
       defined in the parent class.


Constructors - super
Every object contains the instance variables of its class. What isn't so obvious is that every object also
has all the instance variables of all super classes (parent class, grandparent class, etc). These super
class variables must be initialized before the class's instances variables.


Automatic insertion of super class constructor call
When an object is created, it's necessary to call the constructors of all super classes to initialize their
fields. Java does this automatically at the beginning if you don't.
For example, the first Point constructor (see Constructors) could be be written
  public Point(int xx, int yy) {
            super();     // Automatically inserted
            x = xx;
            y = yy;
  }


Explicit call to superclass constructor
Normally, you don't explicitly write the constructor for your parent class, but there are two cases
where this is necessary:
           Passing parameters. You want to call a parent constructor which has parameters (the
            default construct has no parameters). For example, if you are defining a subclass
            of JFrame you might do the following.

             class MyWindow extends JFrame {
                  . . .
                  //======== constructor
                  public MyWindow(String title) {
                       super(title);
                       . . .
            In the above example you wanted to make use of the JFrame constructor that takes a title as
            a parameter. It would have been simple to let the default constructor be called and use a
            setter method as an alternative.

              class MyWindow extends JFrame {
                    . . .
                    //======== constructor
                    public MyWindow(String title) {
                      // Default superclass constructor call automatically
              inserted.
                         setTitle(title);        // Calls method in superclass.
                         . . .
           No parameterless constructor. There is no parent constructor with no parameters.
            Sometimes is doesn't make sense to create an object without supplying parameters. For
            example, should there really be a Point constructor with no parameters? Altho the previous
            example (see Constructors) did define a parameterless constructor to illustrate use of this, it
            probably isn't a good idea for points.


Constructor Puzzle
This class compiles without a problem
      /////////////////// class WITHOUT a parameterless
      constructor.//////////////////
1
     class Parent {
         int _x;
2
            Parent(int x) {                 // Constructor with a parameter.
3               _x = x;
            }
     }
4

5

6

7

8

9



But why won't this subclass compile?
     ////////////////// Why won't this class compile?
     ///////////////////////////////
1
     class Child extends Parent {
         int _y;
2
            Child(int y) {                // This line mysteriously generates an error!
                _y = y;
3
            }
     }
4

5

6

7

8




Hint
The error message from the compiler is:
       Child.java:5: cannot find symbol symbol : constructor Parent()
But you defined a constructor for   Parent, and anyway, you didn't even call the Parent constructor, so what's the problem with line 5?


Constructor chaining - implicit or explicit constructor call as first statement
Before you can initialize an object in a constructor, the object's parent constructor must be called first. If you don't write an explicit call to
the   super() constructor, Java automatically inserts one in your constructor. The compiler automatically inserts superclass constructor
calls in both constructors.

            Parent(int x) {
                    super();           // Compiler inserts this statement to call Object().
                    _x = x;
            }
This is fine because there is a parameterless constructor for Object. However, when the       Child class constructor is modified to call its
superclass constructor, there's a problem.

            Child(int y) {
                    super();           // Compiler inserts this statement to call Parent().
                    _y = y;
            }


No parameterless constructor
                      Parent class has no parameterless constructor. When any constructor is explicitly defined (as
The problem is that the
in   Parent above), the compiler no longer produces a default parameterless constructor.


Possible solution 1 - Explicit constructor call
Usually the best solution is for the subclass constructor to explicitly call the superclass constructor so that its fields are correctly initialized.

            Child(int y) {
                    super(-666);               // Make explicit call to superclass constructor.
                    _y = y;
            }


Possible solution 2 - Define a parameterless constructor
But no invalid values please. Advice you will sometimes see is to always define a parameterless constructor, so that this problem doesn't
occur. But an essential element of data encapsulation is that the value of a object can be guaranteed to be a legal value. A constructor
insures that the initial value of an object is valid. Many objects can't be given a valid value with a default constructor. This peculiar semantic-
free example    Parent class might be changed to have a parameterless constructor as follows (supposing that a value of -666 makes sense
for this class):

        /////////////////// class with parameterless constructor.
        //////////////////////
1
        class Parent {
2           int _x;

                Parent() {                        // Parameterless constructor
3
                    this(-666);                   // Call other constructor with default value.
             }
4
             Parent(int x) {                  // Constructor with a parameter.
                 _x = x;
5
             }
        }
6

7

8

9

10

11

12

13



Example class where a default constructor would be a disaster
It's common to have a class with no legal default values. For example, what should the default constructor do for this class?

      // A parameterless constructor would be wrong here.
    1
      public class Student2 {
    2     private String firstName; // First name
          private String lastName; // Last name
    3
          private int    id;        // Student id
    4
          //====================================================== constructor
    5
          public Student2(String fn, String ln, int idnum) {
    6         firstName = fn;
              lastName = ln;
    7
              id        = idnum;
    8     }
    9        //======================================== parameterless constructor
 10          public Student2() {
                 ????              // No possible legal values.
 11          }
 12
             //========================================================== setters
 13          public void setID(int id) {
 14              this.id = id;
             }
 15
             . . .
 16 }
 17
 18
 19
 20
 21
 22
 23
 24
 25

If you defined a default constructor for   Student2, what would you assign to the fields - null for the names and zero for the id?
Whatever you choose it's illegal. There are setters so you hope that the user will set the fields to legal values. Or you will check for the illegal
initial values and throw an exception or give some other error when there is an attempt to use them. Perhaps there are times when this is
acceptible in a small one-person project, but it's a disaster waiting to happen in anything larger.

Never define a parameterless constructor unless it can create a valid object.



Interfaces
An interface is a list of methods that must be defined by any class which implements that interface.It may also define constants
(public static final).

Similar to abstract class. An interface is similar to a class without instance and static variables (static         final constants are
allowed), and without method bodies. This is essentially what a completely abstract class does, but abstract classes do allow static method
definitions, and interfaces don't.

Contractual obligation. When a class specifies that it implements an interface, it must define all methods of that interface. A class can
implement many different interfaces. If a class doesn't define all methods of the interfaces it agreed to define (by the implements clause), the
compiler gives an error message, which typically says something like "This class must be declared abstract". An abstract class is one that
doesn't implement all methods it said it would. The solution to this is almost always to implement the missing methods of the interface. A
misspelled method name or incorrect parameter list is the usual cause, not that it should have been abstract!

A very common use of interfaces is for listeners. A listener is an object from a class that implements the required methods for that
interface. You can create anonymous inner listeners, or implement the required interface in any class.

Interfaces are also used extensively in the data structures (Java Collections) package.



Classes versus Interfaces
Classes are used to represent something that has attributes (variables, fields) and capabilities/responsibilities (methods,
functions). Interfaces are only about capabilities. For example, you are a human because you have the attributes of a human (class). You
are a plumber because you have the ability of a plumber (interface). You can also be an electrician (interface). You can implement many
interfaces, but be only one class.

This analogy fails in one way however. Capabilities (methods) of a class are unchanging (if a class implements an interface, it is implemented
for all instances), whereas the human skills we're talking about are dynamic and can be learned or forgotten. The analogy is flawed, as all
analogies are, but it gives some idea of a distinction between classes and interfaces.



Interfaces replace multiple inheritance
Simpler. A C++ class can have more than one parent class. This is called multiple inheritance. Managing instance variable definitions in
multiple inheritance can be really messy, and leads to more problems (eg, the "Deadly Diamond of Death") than solutions. For this reason
Java designers chose to allow only one parent class, but allow multiple interfaces. This provides most of the useful functionality of multiple
inheritance, but without the difficulties.
Implementing an Interface
You may implement as many interfaces in a class as you wish; just separate them with commas. For example,

   // Note:
   //        ActionListener requires defining actionPerformed(...)
   //   MouseMotionListener requires defining mouseMoved(...) and
   mouseDragged(...).


   public class MyPanel extends JPanel implements ActionListener,
   MouseMotionListener {
           public void actionPerformed(ActionEvent e) {
                  /* Method body */
           }
           public void mouseDragged(MouseEvent me) {
                  /* Method body */
           }
           public void mouseMoved(MouseEvent me) {
                  /* Method body */
           }
           // Everything else in this class.
   }
It is common for a panel that does graphics and responds to the mouse to implement its own mouse listeners (but not action listeners) as
above.



Declaring an interface
For simple programs you are more likely to use an interface than define it. Here is what the java.awt.event.ActionListener interface definition
looks something like the following.

   public interface ActionListener {
               public void actionPerformed(ActionEvent e);
   }


Tagging Interfaces
Java defines a few interfaces that are just used as a boolean property of a class, but don't actually require the implemenation of any methods.
These are called tagging interfaces.

Tagging interfaces are an abuse of the interface principle, but Java makes use of object-oriented features to solve all problems if possible,
rather than invent a more appropriate feature.

Common tagging interfaces that you might see are:


Cloneable              Implementing this interface indicates that the class has overridden Object's    clone() method. But there is no
                       check that this is true, and because subclasses inherit interfaces, it will look like all subclasses have
                       defined   clone() altho that is not necessarily true. Yes, this is not the normal spelling of the English word. ???
                       Why needed.

Serializable           This tagging interface indicates that a class can serialized - that an object of this class can be written out and read
                       back in using ???. This can be useful for short-term storage of objects, but should not be used for long-term storage
                       because any change to the class definition makes that persistent copy unreadable!




Class class
Like a human thinking about his/her own thinking, the process of a running program examining its classes is called reflection or introspection.

There is run-time information about classes that you can access. The central class representing this information
is   java.lang.Class, a class confusingly named Class.


Use the Object getClass() method to get a Class object

Every class has the class   Object as an ancestor. A reflection method in the Object class is getClass(), which returns the Class of
that object.



Class methods
java.lang.Class has two useful methods: getName() for getting a string name of the class
andgetSuperclass() for getting the Class object of the parent class, or null if this is the Object class. For example,

      String s = "abc";
      Class cls;
      cls = s.getClass();                  // Represents the String class.
      System.out.println(cls.getName()); // Prints "java.lang.String"


Example - What class is the content pane?
                                               getContentPane() method. The documenation says it returns
I wanted to know the type returned by the JFrame
a    Container object, but that only means that it returns Container or a subclass of Container. This program prints the
inheritance hierarchy for any object. Change SIMPLE to false if you want to see the name with its package qualifications.

        //   File   : oop/reflection/InheritanceLister.java
        //   Purpose: Demo reflection using the Class class.
1
        //   Author : Fred Swartz -- 2006-11-04
        //   Enhancements: Perhaps output something that can be read by UMLGraph.
2       //   NOTE: simpleName() returns zero length name for anon classes!

        import java.awt.*;
3
        import javax.swing.*;
        import java.util.*;
4
        class InheritanceLister {
            //================================================================
5
        constants
            private static final boolean SIMPLE = true;
6
            //==============================================================
        method main
7           public static void main(String[] args) {
                JFrame f = new JFrame();
8               Container c = f.getContentPane();
                System.out.println("\n---Content pane inheritance hierarchy");
                printAncestors(c);
9
           LayoutManager lm = c.getLayout();
           System.out.println("\n---Show default layout for content pane +
10
   ancestors.");
           printAncestors(lm);
11
           System.out.println("\n---Default JPanel layout inheritance
   hierarchy");
12
           printAncestors((new JPanel()).getLayout());
       }
13

       //==================================================== method
14
   printAncestors
       private static void printAncestors(Object obj) {
15         for (Class cls : getAncestorList(obj)) {
               String name = SIMPLE ? cls.getSimpleName() : cls.getName();
               if (name.length() == 0) {
16
                   //... Must be an anonymous class.
                   name = "[Anonymous inner class]";
17             }
               System.out.print("   " + name);
18             //... Get array of interfaces that this class implements.
               boolean firstTime = true;
19             for (Class inter : cls.getInterfaces()) {
                   if (firstTime) {
                       System.out.print(" implements ");
20                     firstTime = false;
                   } else {
21                     System.out.print(", ");
                   }
                   name = SIMPLE ? inter.getSimpleName() : inter.getName();
22                 System.out.print(name);
               }
23             System.out.println();
           }
       }
24
       //=================================================== method
25 getAncestorList
       private static ArrayList<Class> getAncestorList(Object obj) {
           ArrayList<Class> result = new ArrayList<Class>();
26
           for (Class cls = obj.getClass(); cls != null; cls =
27 cls.getSuperclass()) {
               result.add(cls);
           }
28
           Collections.reverse(result); // For normal top-down hierarchy.
29
           return result;
       }
30 }
31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51
52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

The output from this program is

---Content pane inheritance hierarchy
   Object
   Component implements ImageObserver, MenuContainer, Serializable
   Container
   JComponent implements Serializable, HasGetTransferHandler
   JPanel implements Accessible

---Show default layout for content pane + ancestors.
     Object
     BorderLayout implements LayoutManager2, Serializable
     [Anonymous inner class]

---Default JPanel layout inheritance hierarchy
   Object
   FlowLayout implements LayoutManager, Serializable
                              JPanel, and its layout is an anonymous subclass of BorderLayout. The default layout for a
So the default content pane is a
normal   JPanel is just an ordinary FlowLayout.

				
DOCUMENT INFO
Shared By:
Tags:
Stats:
views:27
posted:7/27/2012
language:English
pages:13