Overriding Base Class Methods


Another Inheritance Example: Person - Student

Let’s now take a look at a more real-world example of inheritance. This example will utilize the Person class presented in chapter 9 as a base class. The derived class will be called Student. Let’s take a look at the UML diagram for this inheritance hierarchy.

The Person - Student UML Class Diagram

Figure 11-5 gives the UML class diagram for the Student class inheritance hierarchy. Notice the behavior provided by the Person class in the form of its public interface methods. The Student class extends the functionality of Person and provides a small bit of specialized functionality of its own in the form of the getStudentInfo() method.

image from book
Figure 11-5: UML Diagram Showing Student Class Inheritance Hierarchy

Since the Student class participates in an is-a relationship with class Person, a Student object can be used where a Person object is called for in your source code. However, now you must be keenly aware of the specialized behavior provided by the Student class as you will soon see when you examine and run the driver application program for this example.

Person - Student Source Code

Example 11.4: Person.java

image from book
 1    import java.util.*; 2 3    public class Person { 4      private String first_name = null; 5      private String middle_name = null; 6      private String last_name = null; 7      private Calendar birthday = null; 8      private String gender = null; 9 10     public static final String MALE = "Male"; 11     public static final String FEMALE = "Female"; 12 13     public Person(String f_name, String m_name, String l_name, int dob_year, 14                   int dob_month, int dob_day, String gender){ 15       first_name = f_name; 16       middle_name = m_name; 17       last_name = l_name; 18       this.gender = gender; 19 20       birthday = Calendar.getInstance(); 21       birthday.set(dob_year, dob_month, dob_day); 22     } 23       24     public int getAge(){ 25       Calendar today = Calendar.getInstance(); 26       int now = today.get(Calendar.YEAR); 27       int then = birthday.get(Calendar.YEAR); 28       return (now - then); 29     } 30 31     public String getFullName(){ return (first_name + " " + middle_name + " " + last_name); } 32 33     public String getFirstName(){ return first_name; } 34     public void setFirstName(String f_name) { first_name = f_name; } 35 36     public String getMiddleName(){ return middle_name; } 37     public void setMiddleName(String m_name){ middle_name = m_name; } 38 39     public String getLastName(){ return last_name; }  40     public void setLastName(String l_name){ last_name = l_name; } 41 42     public String getNameAndAge(){ return (getFullName() + " " + getAge()); } 43 44     public String getGender(){ return gender; } 45     public void setGender(String gender){ this.gender = gender; } 46 47     public void setBirthday(int year, int month, int day){ birthday.set(year, month, day); } 48 49   } //end Person class
image from book

The Person class code is unchanged from chapter 9.

Example 11.5: Student.java

image from book
 1     public class Student extends Person { 2      private String _student_number = null; 3      private String _major = null; 4 5      public Student(String f_name, String m_name, String l_name, int dob_year, 6                     int dob_month, int dob_day, String gender, String student_number, String major){ 7          super(f_name, m_name, l_name, dob_year, dob_month, dob_day, gender); 8          _student_number = student_number; 9          _major = major; 10      } 11 12     public String getStudentInfo(){ 13        return getNameAndAge() + " " + _student_number + " " + _major; 14     } 15    } // end Student class
image from book

The Student class extends Person and implements specialized behavior in the form of the getStudentInfo() method. The Student class has one constructor that takes several String and integer parameters. With the exception of the last two parameters, student_number and major, the parameters are those required by the Person class and in fact they are used on line 7 as arguments to the super() method call. The parameters student_number and major are used to set a Student object’s _student_number and _major fields respectively on lines 8 and 9.

The getStudentInfo() method begins on line 12. It returns a String that is a concatenation of the String returned by the Person object’s getNameAndAge() method and the _student_number and _major fields. Take note specifically of the getNameAndAge() method call on line 13. You will frequently call public or protected base class methods from derived classes in this manner.

This is all the specialized functionality required of the Student class for this example. The majority of its functionality is provided by the Person class. Let’s now take a look at these two classes in action. Example 11.6 gives the test driver program.

Example 11.6: PersonStudentTestApp.java

image from book
 1     public class PersonStudentTestApp { 2       public static void main(String[] args){ 3 4        Person p1 = new Person("Steven", "Jay","Jones", 1946, 8, 30, Person.MALE); 5        Person p2 = new Student("Jeanie", "Sue", "Freeman", 1963, 10, 10, Person.FEMALE, 6                              "000002", "Business"); 7        Student s1 = new Student("Richard", "Warren", "Miller", 1723, 2, 29, Person.MALE, 8                              "000003", "Math"); 9 10       System.out.println(p1.getNameAndAge()); 11       System.out.println(p2.getNameAndAge()); 12      // System.out.println(p2.getStudentInfo());    // error - p2 is a Person reference 13       System.out.println(s1.getNameAndAge()); 14       System.out.println(s1.getStudentInfo()); 15       } 16    }
image from book

This program is similar in structure to example 11-3 in that it declares three references and shows you the effects of calling methods on those references. A Person reference named p1 is declared on line 4 and initialized to point to a Person object. On line 5, another Person reference named P2 is declared and initialized to point to a Student object. On line 7 a Student reference is declared and initialized to point to a Student object.

The method calls begin on line 10 with a call to the getNameAndAge() method on a Person object via the p1 reference. This will work fine. On line 11 the getNameAndAge() method is called on a Student object via the p2 reference, which, as you know, is a Person-type reference.

Line 12 is commented out. This line, if you try to compile it in its current form, will cause a compiler error because an attempt is being made to call the getStudentInfo() method, which is specialized behavior of the Student class, on a Student object, via a Person-type reference. Now, repeat the previous sentence to yourself several times until you fully understand its meaning. Good! Now, you may ask, and rightly so at this point, “But wait...why can’t you call the getStudentInfo() method on a Student object?” The answer is — you can, but p2 is a Person-type reference, which means that the compiler is checking to ensure you only call methods defined by the Person class via that reference. Remember the “ Java is a strongly-typed language... ” spiel I delivered earlier in this chapter? I will show you how to use casting to resolve this issue after I show you how this program runs.

Continuing with example 11.6 — on line 13 the getNameAndAge() method is called on a Student object via a Student reference. This is perfectly fine since a Student is a Person. On line 14 the getStudentInfo() method is called on a Student object via a Student reference. This also performs as expected. Figure 11-6 gives the results of running example 11.6.

image from book
Figure 11-6: Results of Running Example 11.6

Casting

OK, now let’s take a look at a modified version of example 11.6 that takes care of the problem encountered on line 12. Example 11.7 gives the modified version of image from book PersonStudentTestApp.java.

Example 11.7: PersonStudentTestApp.java (Mod 1)

image from book
 1     public class PersonStudentTestApp { 2       public static void main(String[] args){ 3 4        Person p1 = new Person("Steven", "Jay","Jones", 1946, 8, 30, Person.MALE); 5        Person p2 = new Student("Jeanie", "Sue", "Freeman", 1963, 10, 10, Person.FEMALE, 6                              "000002", "Business"); 7        Student s1 = new Student("Richard", "Warren", "Miller", 1723, 2, 29, Person.MALE, 8                              "000003", "Math"); 9 10       System.out.println(p1.getNameAndAge()); 11       System.out.println(p2.getNameAndAge()); 12       System.out.println(((Student)p2).getStudentInfo());    // casting resolves the issue 13       System.out.println(s1.getNameAndAge()); 14       System.out.println(s1.getStudentInfo()); 15       } 16    }
image from book

Notice on line 12 that the compiler has been instructed to treat the p2 reference as though it were a Student reference. This form of explicit type coercion is called casting. Casting only works if the object really is of the type you are casting it to. In other words, you would be in big trouble if you tried to cast a Person to a Car since a Person is not a Car. Figure 11-7 shows the results of running this program.

image from book
Figure 11-7: Results of Running Example 11.7

Use Casting Sparingly

Casting is a helpful feature but too much casting usually means your design is not optimal from an object-oriented point of view. You will see more situations in this book where casting is required, but mostly, I will try and show you how to design programs that minimize the need to cast.

Quick Review

The Person class provided the default behavior for the Student class. The Student class inherited Person’s default behavior and implemented some specialized behavior of its own. Reference variables have an associated type. Method calls to an object pointed to by a reference will succeed without casting so long as the type of the reference supports the method you are trying to call. You can force, or coerce, the compiler to treat a reference to an object of one type as if it were a reference to an object of another. This is extremely helpful in some circumstances but, as a rule, casting should be used sparingly. Also, casting only works if the object really is of the type you are casting it to.




Java For Artists(c) The Art, Philosophy, and Science of Object-Oriented Programming
Java For Artists: The Art, Philosophy, And Science Of Object-Oriented Programming
ISBN: 1932504052
EAN: 2147483647
Year: 2007
Pages: 452

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net