Title: Inheritance
Course: CPS 161: An Intro to Programming with Java - DL MM MASTER

Inheritance

Basics

1. Reason for Inheritance - avoid replicating code when you need something similar
2. Families of classes - Drawing program (Shape, Circle, Rectangle, etc.)
The Animal kingdom is full of good inheritance examples.
Chess - Piece class, Knight, Bishop, etc.
Book's example - Employee, HourlyEmployee, SalariedEmployee etc. (See figure at the start of the Inheritance chapter (chapt 7)
3. Terminology - (Base class, Derived class), (superclass, subclass), (Parent class, child class)
4. An "IS A" relationship should exist between a base class and it's derived class. An HourlyEmployee is an Employee. Constrast this with a "Has A" relationship. Consider a class called Car which contains classes Engine, Transmission, 4 wheels. Now consider another class called Jeep which is derived from Car. Note that even though this is the way things should go, the compiler has no way to enforce proper relationships. Inheritance is associated with "IS A" relationships. We also have the term Composition for the "Has A" relationships.
5. Take a look at the Employee, HourlyEmployee - Note the way constructors work - House analogy. Note the calls to super in HourlyEmployee. super() must be first. Put some print statements into the constructors and construct HourlyEmployee and see what happens as well as what is callable. Create something similar to the lab (Person, Student, Family).
6. Inheritance allows us to add functionality to a class, and to override methods - see the toString method in HourlyEmployee. Note that if the calling sequence does not match, then we are not overriding, but we are overloading. Consider adding toString with a parameter.
7. Note that in overriding, the return type must also stay the same with one exception. In release 1.5 it was allowed to return "covariant" return types. So a return of Employee could be changed to HourlyEmployee. Note that an HourlyEmployee has an "Is A" relationship to Employee.
8. Access on an overriden method can become more accessable (i.e. we can have a base class method that is private that becomes public in the derived overridden method). However, access cannot become less accessable.
9. Note the super calls in HourlyEmployee. Note that leaving off a super call results in the default super call.
10. Usage of the keyword "this" to have a constructor call another constructor. Take a look at Employee to see how this could be done.
11. Take a look IsADemo.java and note that both classes can be considered Employee type.
12. Go over StringTokenizer and EnhancedStringTokenizer.java -- note the new routine:
public String[] tokensSoFar()

We will rework the ChessGame code from "Arrays Second Half of Chapter" notes.

Consider ChessPiece with properties of color, col, row, move(xdelta, ydelta), isLegalMove(xdelta, ydelta), getType(), toString, equals

ChessGame contains an array of ChessPiece

Now add classes Knight, Rook, etc that override move, isLegalMove and getType , toString, equals

Add toString to ChessGame (To put out end of line characters us System.getProperty("line.separator") )

In main, add some logic to move a numbered piece some delta distance.

On your lab, you will be looking at Person, Student

Self Test Exercises:

1. The class HourlyEmployee has methods named getName and getRate. Why does the definition of the class HourlyEmployee contain a definition of the method getRate but no definitions of the methods getName?
2. Given the Employee.java, HourlyEmployee.java and SalariedEmployee.java classes, is the following legal?


	public class EmployeeDemo
	{
	    public static void main(String[] args)
		{
		    HourlyEmployee joe = new HourlyEmployee("Joe Young",
			         new Date("February", 1, 2004), 10.5, 40);
			SalariedEmployee boss = new SalariedEmployee("Mr. Big Shot",
			         new Date("January", 1, 1999), 100000);
		    printName(joe);
			printName(boss);
	    }
	   public void printName(Employee object)
	   {
	       System.out.println(object.getName());
	   }
	}
	

3. Give a definition for a class TitledEmployee that is a derived class of the base class SalariedEMployee. The class TitledEmployee has one additional instance variable of stype String called title. It also has two additional methods: getTitle, which takes no arugments and returns a String, and setTitle, which is a void method that takes one argument of type String. It also overrides (redefines) the method definition for getName, so that the string returned includes the title as well as the name of the employee.

More Access modifiers

New access modifiers: protected and "package access" or "friendly access"

Definitions:

- private - only accessable when inside class
- public - accessable to the whole world
- protected - accessable to classes derived from the base class
- "package access" - public while in the same package, but private in any other package

1. Create 2 packages one and two.
2. Demo the above by creating a class A in package one with variables and/or methods with all of the above accesses.
3. See what is accessable in class B which is also in package one.
4. See what is accessable in class C derived from A also in package one.
5. See what is accessable in class D in package two.
6. See what is accessable in class E which is derived from class A in package two.

Self-Test Exercises

1. Would the following be legal for the definition of a method to add to the class Employee


	public void crazyMethod()
	{
	    Employee object = new Employee("Joe", new Date("January", 1, 2005));
		System.out.println("Hello " + object.name);
	 }
	

Would it be legal to add this crazyMethod the class HourlyEmployee?
2. Suppose you change the modifier before the instance variable name from private to public in the class Employee. Would it then be legal to add the method crazyMethod to the class Hourly Employee?
3. Suppose you change the modifier before the instance variable name from private to protected in the class Employee. Would it then be legal to add the method crazyMethod to the class HourlyEmployee.
4. Which is more restricted, protected access or package access?
5. Redefine the toString method of the class SalariedEmployee so that it uses super.toString()
6. Redefine the equals method for the class HourlyEmployee using super.equals to invoke the equals method of the base class Employee.
7. Is the following program legal?


  public class EmployeeDemo
  {
      public static void main( String[] args)
	  {
	      HourlyEmployee joe = new HourlyEmployee("Joe Young",
		                   new Date("Feb", 1, 2004), 10.50, 40);
		  String nameNDate = joe.super.toString();
		  System.out.println(nameNDate);
	  }
  }


8. Suppose you add the following defined constant to the class Employee:


  public static final int STANDARD_HOURS =160; // per month


Would it then be legal to add the following to the class HourlyEmployee


  public void setHoursToStandard()
  {
      hours = STANDARD_HOURS;
  }


Object class issues

1. All classes are derived from Object even if there is no extends keyword
2. Take a look at the definition of the Object class in the Java API documention (start with package java.lang)
3. Note the methods toString(), equals() - note that the equals method is defined differently than we have in Employee and HourlyEmployee. This means that we have been overloading equals instead of overriding. Although this is OK for many applications, there will come a time where some of our standard Java libraries will NOT work if we have an improperly defined Equals method. So we need to see how to do it
4. Approach 1 and its flaws:


  public boolean equals(Object otherObject)
  {
      Employee otherEmployee = (Employee)otherObject);
	  return (name.equals(otherEmployee.name) &&
	             hireDate.equals(otherEmployee.hireDate));
  }


What happens if user passes a null? What happens if an object is passed which is not an Employee?
5. Approach 2 (bullet proof):


  public boolean equals(Object otherObject)
  {
      if (otherObject == null) return false;
	  if (getClass() != otherObject.getClass()) return false;
	
	  Employee otherEmployee = (Employee)otherObject);
	  return (name.equals(otherEmployee.name) &&
	             hireDate.equals(otherEmployee.hireDate));
  }


6. Another approach that is not symmetric. Suppose for Employee, we do the following:


  public boolean equals(Object otherObject)
  {
      if (otherObject == null) return false;
	  if (!(otherObject instanceOf Employee)) return false;
	
	  Employee otherEmployee = (Employee)otherObject);
	  return (name.equals(otherEmployee.name) &&
	             hireDate.equals(otherEmployee.hireDate));
  }


And for HourlyEmployee we do the following:


  public boolean equals(Object otherObject)
  {
      if (otherObject == null) return false;
	  if (!(otherObject instanceOf HourlyEmployee)) return false;
	
	  HourlyEmployee otherHourlyEmployee = (HourlyEmployee)otherObject);
	  return (super.equals(otherHourlyEmployee)
             && (wageRate == otherHourlyEmployee.wageRate)
             && (hours    == otherHourlyEmployee.hours));
  }


The problem with this can be seen in the following:


  Employee e = new Employee("Joe Worker", new Date("January", 1, 2004));
  HourlyEmployee hourlyE  = new HourlyEmployee("Joe Worker", new Date("January", 1, 2004),
                                                  50.50, 160);
												
	// Note that the following gives a true:
	e.equals(hourlyE);
	
	// But the following gives a false
	hourlyE.equals(e);


Self-Test Exercises:

1. Redefine the equals method of the class SalariedEmployee so that it has a parameter of type Object and follows the guidelines of the book that we discussed.
2. Redefine the Date class from chapter 4 to have a proper equals method.
3. What is the output produced by the following program?


  public static void main(String[] args)
  {
      Employee object1 = new Employee();
	  Employee object2 = new HourlyEmployee();
	  if (object1.getClass() == object2.getClass())
	      System.out.println("Same class");
	  else
	      System.out.println("NOT the same class");
  }


Exercises:

1. Consider some of the options, issues, etc. for a class named Square which is derived from a class named Rectangle see code below:
Add toString, equals methods to Square. Can I call area, perimeter for a square, boundingRectangle, intersectingRectangle.

Suppose that I add public setters and getters for Rectangle ... What happens if they get called from Square. What can I do to protect Square?



public class Rectangle {
    private int height, width;
    private int x, y;
    public Rectangle(int x, int y, int w, int h)
    {
        this.x =x;
        this.y = y;
        width=w;
        height =h;
    }
    public Rectangle()
    {
        this(1,1,1,1);
    }
    public String toString()
    {
        return "Rectangle: width="+width +"height="+height;
    }
    public boolean equals(Object obj)
    {
        if (getClass() != obj.getClass())
            return false;
        Rectangle r=(Rectangle)obj;
        if (x==r.x && y==r.y && width==r.width && height == r.height)
            return true;
        else
            return false;
    }
    public int area()
    {
        return height*width;
    }
    public int perimeter()
    {
        return 2*(width+height);
    }
    Rectangle boundingRectangle(Rectangle other)
    {
        int x_new = Math.min(x, other.x);
        int y_new = Math.min(y, other.y);
        int w_new = Math.max(x+width, other.x+other.width) - x_new;
        int h_new = Math.max(y+height, other.y+other.height) - y_new;
        return new Rectangle(x_new, y_new, w_new, h_new);
    }

    Rectangle intersectingRectangle(Rectangle other)
    {
        int x_new = 1;// Fill in real code
        int y_new = 1;// Fill in real code
        int w_new = 1;// Fill in real code
        int h_new = 1;// Fill in real code
        if (w_new > 0 && h_new > 0)
            return new Rectangle(x_new, y_new, w_new, h_new);
        else
            return null;
    }



    public static void main(String[] args) {
        //Create some code using the above:

    }

}



Last Modified: July 14, 2013 4:01 PM