Java Inheritance

This page contains course notes for Object Oriented Programming taught in the Spring of 2011. If you have come here from a search engine or the like, you may wish to visit the course home page for more material, or visit my general teaching page for possibly more up to date versions, or perhaps my home page
  1. Encapsulation and information hiding are just one basic property of OOP. It gives us objects, but the benefit doesn't seem that great. Good thing that once we have objects, we can add OTHER properties. The next property we'll talk about is inheritance.
  2. Inheritance starts with organizing our classes in a hierarchy. Hierarchies are all over the place in the universe. One you know well is the military hierarchy. At the top is the commander in chief. Connected underneath him are the joint chiefs of staff. Then, underneath the CNO, are other admirals, etc., all the way down to, somewhere near the bottom, you.
  3. The military hierarchy is a little different than what we're dealing with here. Instead we want "kind-of" hierarchies. A classic example is the "Linnaean taxonomy", from Domain to Kingdom, Phylum, Class, Order, Family, Genus, Species, with the top breaking up into plan, animal, fungi, bacteria, and protista. (give or take, depending on who you ask).
  4. A classic example of this in programming comes in simulations and games, like our Tron Light Cycle game. In these cases you might start with a class, PhysicalObject. Underneath that might be StationaryObject and MovableObject. MoveableObject might break into PassiveMoveable and Vehicle. Vehicle could then be divided into cars and cycles, etc.
  5. Another common example are GUI interface objects. You might have GUI Objects as a class, and then Windows, Menus, Buttons, and Fields as subclasses. Each fields could be broken into display fields and InputFields, and InputFields can be further specialized into PasswordInputFields.
  6. All of this doesn't tell us why we want to organize it this way. The reason is when a class is a child class of a parent class, the child class inherits all of the data (fields) and all of the methods from the parent.
  7. This should make some sense: if the child class is a special kind of the parent class (An elephant is a special kind of mammal, a cycle is a kind of vehicle, a button is a kind of GUI widget) then the child should have similar functionality and would likely need the same fields an use the same methods (elephants regulate their temperature, cycles carry passengers, button change GUI behavior).
  8. For some operations, nothing would be defined in the parent class because all of the child classes handle it differently. Elephants locomote differently from dolphins, so it would not makes sense for them both to inherit the same locomotion method.
  9. So enough with the metaphors, what would this look like?
      public class Polygon {
        int sideLengths[];
        int numSides =0;
    
        public Polygon(int [] lengths){
          sideLengths = lengths;
          numSides = lengths.length;
        }
      
        public int perimeter() {
      //compute perimeter
          int sum = 0;
          for (int i = 0 ; i <  sideLengths.length ;i++) {
            sum += sideLengths[i];
          }
          return sum;
        }
    
        //No area method.
      }
    
      public class Triangle extends Polygon {
    
        public Triangle(int [] lengths) {
          super(lengths);  //duper
          numSides = 3;
        }
        public Triangle () {
          this(new int[3]);
        }
        //No perimeter needed
    
        public double area (){
          double s = perimeter()/2;
          //Heron's formula
          return Math.sqrt(s*(s- sideLengths[0])*(s- sideLengths[1])*(s - sideLengths[2]));
        }
      }
    
  10. Sometimes a parent class implements a method but we might want to do the same thing but differently for the child
      public class Rectangle extends Polygon {
        public double area() {
          return sideLengths[0]*sideLengths[1];
        }
      }
    
      public class Square extends Rectangle {
        publuc double area() {
          return sideLengths[0] * sideLengths[0];
        }
      }
      
  11. In this case the say that the area in Square overrides the area in rectangle. To shut netbeans up about a warning when you do this, add the @Override tag to the method (NOT A JAVADOC COMMENT):
      public class Square extends Rectangle { 
        @Override
        publuc double area() { 
          return sideLengths[0] * sideLengths[0]; 
        } 
      } 
      

    Some things to think about:
    1. Would you make a class hierarchy for the Tron Cycles game? If so, what might you want to inherit from what?
    2. What if we had some cycles that did not leave trails, would inheritance be a good idea then?
    3. What about if we added a professor class to lab 5? How would we organize that?
  12. Much of the time, we make subclasses when we have a special case of a class, just like above. But another use for extending a class is to add functionality to the superclass.
  13. Let's say we want to keep track of how often a string occurs in a webpage. We could make a class that has fields of String and int, OR we could extend String, and add the field:
      public class CountableString extends String {
        int count;
      }
      
  14. Why would we want to do this instead of just making a class that contained the string? Because we get all sorts of other methods fro free, such as the compareTo() method. Otherwise we would have to write it in order to sort our new class.
  15. What's the disadvantage? Clarity. If String is a member field, it is made explicit what is being represented. By extending, we have data fields defined in multiple places.
  16. How do we decide when to use extending for enhancement, and when to use fields? That's something of an art, but in general the closer the new class is to an existing class, and the more you want to use already written functions, the more you want to extend the class.
  17. Dirty little secret: String was declared final, as in: public final class String { . This means we can't actually derive anything off it. If we try, we get:
    Foo.java:1: cannot inherit from final java.lang.String
    public class Foo extends String {

    So let's look at another example. Below is a basic position class from our Tron game:
    public class Pos
    {
      private int  r, c, d;
      public Pos(int row, int col, int dir)
      {
        r = row; c = col; d = dir; 
      }
      public void moveForward()
      {
        int[] dr = { -1, 0, 1, 0 };
        int[] dc = {  0, 1, 0,-1 };
        r += dr[d];
        c += dc[d];
      }
      public void turnRight()
      {
         d = (d + 1)%4;
      }
      public void turnLeft()
      {
         d = (d + 3)%4;
      }
      public int getRow()
      {
        return r;
      }
      public int getCol()
      {
        return c;
      }
      public int getDir()
      {
        return d;
      }
      public String toString()
      {
        return "(" + r + "," + c + "," + d + ")";
      }
      public static void main(String[] args)
      {
        Pos p = new Pos(4,7,1);
        System.out.println(p);
        p.moveForward();
        System.out.println(p);
      }
    }
    
    What is we wanted to label our positions in some way? In this case we could extend the position class, and add a label as a string. Notice how we get all sorts of other stuff for free, and we can use things like super.toString() in our own toString() to reuse as much as possible.
  18. Many OOP languages allow for multiple class hierarchies, but java allows just one. All classes descend from the base class Object. If you don't say 'extends' your class is automatically extends Object. This gives several advantages we'll talk about later, but one is that they can put some methods in Object directly. toString() is one such method. The toString() in Object converts the pointer address to a string; have we seen that before?
  19. Whenever you write toString(), you are overriding the toSting() in Object.