You must always use the reserved word super to use a method from the superclass in the subclass.

INHERITANCE

TOPICS

-      Objects, Classes, OOD and OOP

-      Object-Oriented Design: Basic Principles

-      Inheritance

o   Rules and facts about superclass/subclass

o   Constructors (superclass/subclass)

o   Protected members of a class

o   The Object class

-      Programming Samples

o   Inheritance: Class Rectangle - Class Box

o   Inheritance: Class Time - Class ExtendedTime

OUTLINE

1. Objects, Classes, OOD and OOP
 

-      Object-oriented analysis, object-oriented design (OOD) and object-oriented programming (OOP) are based on entities known as objects. An object has a state (whose representation is hidden) and a defined set of operations that operate on that state. The state is represented as a set of object attributes. Operations associated with an object provide services to other objects (clients), which request these services when some computation is required.

-      The fundamental idea behind object-orientation is to combine into a single unit both data and the functions that operate on that data (encapsulation). An object’s functions or methods are the means of accessing that data. This data is actually hidden from the user or other programs.

-      Each object is an instance of a class. A class definition totally defines the behavior and attributes of objects of that particular class.

-      (Reminder) Some definitions:

o   Object. Objects encapsulate data and operations that need to be performed on that data. Objects have interfaces that only allow authorized operations to be performed on data (generally known as the access methods.) Thus data remains safe from malicious or inadvertent changes. Once defined, objects can be used as basic data types within a program. An object has a state, presents an interface and exhibits a behavior. The state is determined by the value of the object’s internal data, which results from the operations performed on that data by changing its state. The variables representing the internal state of an object are called instance variables. The collection of methods determines the object’s interface and behavior. Also called: class object or class instance; variable of type class

o   Class. A class is a generalized description of the characteristics of similar objects. It is a template from which objects may be created by invoking certain methods called the constructor methods. Constructor methods are generally called automatically when an object is instantiated and serve to allocate memory, initialize object state, etc. Similarly, when these objects are destroyed, destructor methods are automatically invoked which are generally used to release the allocated memory, close open files, perform garbage collection etc. Objects of the same class have common operations and therefore uniform behavior. Classes have one or more interfaces that specify the operations accessible to clients through that interface. A class body specifies code for implementing operations in the class interface.

o   Message. Messages are signals sent from one object to another that request the receiving object to execute one of its methods. Messages are similar to function/method calls, i.e., they tell an object which service or state change it should perform.

o   Methods. Methods are procedures contained within an object that are executed in response to a message. Depending upon the language, most or all of the communication between objects takes place by sending messages that invoke methods.

-      OOD

o   First step in the problem-solving process with an object-oriented approach = identify the components ("objects") which form the basis of the solution, and determine how these objects interact with each other. Example: video store inventory application - objects: videos and customers.

o   Next step: Specify for each object the relevant data and possible operations to be performed on that data. Example: video store inventory application - the data for a movie object may include the movie title, year released, type of movie, director, starring actors, number of copies in store, etc. Some operations on a movie object may include: how many copies not rented, list info for a movie, list info for movies with a common property (query), etc.

o   Remember that the fundamental idea behind object-orientation is to combine into a single unit both data and the methods that operate on that data. In OOD, the final program is a collection of interacting objects.

o   OOD has 3 basic principles:

1.     Encapsulation

2.     Polymorphism

3.     Inheritance

-      A programming language that implements OOD is called an Object-Oriented Programming (OOP) language.

-      Advantages/Disadvantages of OOP

·       Advantages:

Re-use of code. Linking of code to objects and explicit specification of relations between objects allows related objects to share code. Encapsulation and weak coupling between objects means class definitions are more likely to be re-used in other applications. Objects as well as procedures become likely candidates for re-use. The enforcement of a consistent interface to objects lessens code duplication.

Ease of comprehension. Objects relate more closely to real world entities. It, therefore, becomes easier to model the user domain as a set of interacting objects, and then transform that model into a suitable application using an object-oriented programming language. As the data and operations are hidden inside an object, programmers need not worry about unnecessary details while building an application. They need only concern themselves with the interfaces to that object. Object- orientation, therefore, tends to reduce complexity to a considerable extent. The code and the data structures associated with it can be set up to closely mimic the generic application concepts and processes. High-level code could make some sense even to a non-programmer. The analysis/design/coding phases in application development become more seamless since they can all deal with the same concepts.

Ease of fabrication and maintenance (redesign and extension) facilitated by encapsulation, and data abstraction --> very clean designs. When an object is going into disallowed states, only its methods need to be investigated. This narrows down the search when debugging.

-      Disadvantages:

Resource Overload.  Since an object-oriented program has a much greater processing overhead than one written using traditional methods, it may work much more slowly.

Reusability.  It is not easy to produce reusable objects between applications when inheritance is used. This is because it makes their classes closely coupled to the rest of the hierarchy. With inheritance, objects can become too application specific for reuse. It is not easy to link together different hierarchies --> more difficult to coordinate very large systems.

Complexity.  Message passing between many objects in a complex application can be difficult to trace and debug.

-      Nevertheless, all of these problems are easily outweighed by the potential benefits of object-oriented technology.

2. Object-Oriented Design: Basic Principles
 

-      Encapsulation

o   Definition: The ability to combine data and operations in a single unit (classes). An object therefore becomes a self-contained entity. Operations can directly access the data, but the internal state of an object cannot be manipulated directly.

o   Encapsulation is a form of information hiding (Information hiding = a form of abstraction --> separating the description of how to use a class from the details of the class’ implementation). Encapsulation allows changes to be made to the implementation of a system with minimal effects on the end user. It is a technique by which data is packaged together with its corresponding procedures (methods). The state data in an object is said to be encapsulated and therefore hidden from the outside world. This means that the internal data of an object can only be accessed through the message interface for that object. The way in which the internal data is accessed is hidden from the client. This is because it is neither required nor is it convenient that the designer of the application should be aware of the internal implementation details of the method invoked by a message.

o   Encapsulation is implemented using access control by using access/visibility modifiers (public - accessible by everyone, in particular public members are available to the client programmer; private - accessible only by the methods within the class; protected - to be discussed later)

o   Encapsulation separates interface from implementation

§  Interface: The visible parts of the class; they can be used and/or changed by the client/programmer. A class interface is defined by its public methods.

§  Implementation: The hidden parts of the class; they can be changed by the class creator without impacting any of the client code. In other words, the implementation cannot be corrupted by the client programmer. Private instance variables hide implementation details, promoting encapsulation.

o   NOTE: In general you should NOT provide accessors and mutators for all private instance variables. Encapsulation is best served with a limited class interface.

o   Advantages of using encapsulation:

§  Programmers that use a class do not need to know how the class is implemented, only how to use it

§  The information the client programmer needs to use the class is kept to a minimum

§  Class implementation may be changed with no impact on those who use the class

-      Polymorphism

o   Definition: The ability to use the same expressions to denote different operations. Polymorphism is a word of Greek origin that means having multiple forms.

o   Polymorphism refers to the ability to hide different implementations behind a common interface. With polymorphism, the same message can be interpreted differently by objects of different classes and therefore produce different but appropriate results. One of the most common examples of polymorphism is method overloading. An overloaded method appears to perform different activities depending upon the kind of data sent to it. The computer treats overloaded functions separately on the basis of the number of arguments and their types. Overloaded methods can simplify the task of a programmer by reducing the number of method names to be managed.

o   Polymorphism further reduces programming complexities by allowing common and unified interfaces for related operations.

-      Inheritance

o   Definition: Inheritance = the ability to create new data types from existing data types (in particular, create new classes from existing classes). In other words, specialized objects may be derived from more generic classes of objects.

o   Inheritance is a mechanism through which class definitions can be built up from other class definitions. If a class definition specifies a use of another class definition, it inherits the definition and may then customize this by adding further attributes and operations of its own. Moreover, the inheriting or the child class may redefine operations inherited from the parent class.

o   Multiple inheritance is also possible in which the class has several parents and it inherits the properties of all its parents (supported by C++, NOT supported by Java). The parent class is also known as a superclass whereas the child class may also be referred to as a subclass or a derived class.

o   With single inheritance (supported by Java), an inheritance hierarchy or tree is created. Here a class can inherit attributes from a single superclass.

o   With multiple inheritance, an inheritance network evolves rather than an inheritance hierarchy or an inheritance tree.

o   Effective software development relies on reusing existing code and inheritance is a useful mechanism for supporting code reuse. However, as classes are reused by implementing subclasses, the classes become more complex and more difficult to understand individual components.

-      Definition: is-a Relationship = a hierarchical connection where one category can be treated as a specialized version of another. Examples: a Car is a Vehicle, an Employee is a Person, a Student is a Person, a Polygon is a Figure, etc.

-      Definition: Inheritance Hierarchy = a set of classes that can share common code, connected by is-a relationships. Often drawn as a downward tree of connected boxes or ovals representing classes. Example:

You must always use the reserved word super to use a method from the superclass in the subclass.

 

-      In the tree-like hierarchical structure above, every square is a rectangle; every rectangle is a polygon; every polygon is a closed figure; every closed figure is a figure.

-      Definition: Inheritance = A way to define a new class based on a class that already exists (= a way to group related classes = a way to share code between two or more classes). The new class will inherit the characteristics of the existing class, but also provide some additional capabilities --> will make programming easier (reuse of code, avoid redundant code). Rather than create a completely new class from scratch, we can take advantage of inheritance and reduce software complexity.

-      Inheritance creates new classes by adding code to an existing class. The existing class is reused without modification.

-      Inheritance allows us to group classes into families of related types (Figure), allowing for the sharing of common operations and data.

-      The existing class is called a superclass (or parent class, or base class). The new class based on the superclass is called a subclass (or child class, or derived class). Each subclass, in turn, could become a superclass for a future subclass --> inheritance extends over several generations of classes (multiple levels of subclassing). The subclass receives a copy of every data and method members from its superclass, and then specializes the superclass. A common specialization is to extend the superclass with additional fields, methods, or both.

-      In the tree-like hierarchical structure above, the class Square is a subclass of Rectangle; the class Rectangle is a subclass of class Polygon; the class Polygon is a subclass of class Closed Figure; the class Closed Figure is a subclass of class Figure. The class Figure is the superclass and the classes Closed Figure, Open Figure, Polygon, etc. are subclasses.

-      Definition: Single inheritance = the process by which a subclass inherits characteristics from just one parent (subclass is derived from one existing superclass). Java supports single inheritance.

-      Definition: Multiple inheritance = the process by which a subclass inherits characteristics from more than one parent (subclass is derived from more than one existing superclass). Java does NOT support multiple inheritance.

-      Syntax:

modifier(s) class SubclassName extends SuperclassName modifier(s)
{
    memberList
    //new characteristics of the subclass go here
}

Where  modifier(s) could be  public, private or protected (private by default).
NOTE:
extends is a Java reserved word.

Example:

public class Square extends Rectangle
{
    ...
    //new characteristics of Square go here
}

-      Rules and facts about superclass/subclass:

    1. The private members of the superclass cannot be accessed directly by the members of a subclass. When you write the definitions of the method members of the subclass, you cannot directly access the private members of the superclass. Instead, a private instance variable of the superclass can only be accessed by the public accessor and mutator methods defined in that class.
    2. The public members of the superclass can be inherited either as public members or as private members by the subclass.
    3. The subclass can include additional data and/or method members.
    4. The subclass can redefine (override) the public member methods of the superclass --> in the subclass you can have a method member with the same name, number, and type of parameters as a method member in the superclass. This redefinition applies only to the objects of the subclass, NOT to the objects of the superclass.
    5. There is no special syntax for overriding a method. To override a superclass method, just write a new version of it in the subclass. This will replace the inherited version. NOTE: If the modifier final is placed before the definition of a method, then that method may not be overridden in a derived class. It the modifier final is placed before the definition of a class, then that class may not be used as a superclass to derive other classes.
    6. The subclass can overload the public member methods of the superclass. If the corresponding method in the superclass and the subclass has the same name but different parameters --> method overloading (the method in the subclass is overloading the method from the superclass.) See the Rectangle - Box sample program to understand and compare method overriding and method overloading.
    7. Whether you override a method of the superclass or overload a method of the superclass in the subclass, you must know how to specify a call to the method of the superclass that has the same name as used by a method of the subclass. In general, when writing the definition of the methods of a subclass to specify a call to a public method of a superclass, you do the following:

1. If the subclass overrides a public method of the superclass ---> specify a call to the public method of the superclass by using super (reserved word in Java) followed by the dot operator followed by the method name and parameter list. Syntax: super.methodName(parameter list) Example: super.print(); The reserved word super is used to refer to the immediate superclass of a class. It is only valid to use super to invoke a method from a direct parent. Repeating super will not invoke a method from some other ancestor class.

2. If the subclass does not override a public method of the superclass, you can specify a call to that public method by using the name of the method and an appropriate parameter list. Syntax: methodName(parameter list)

    1. All data members in the superclass are also data members in the subclass (however, remember [1]). All method members of the superclass are also method members in the subclass (unless overridden/overloaded).
    2. Java expects at least 2 methods to be implemented in virtually all classes (because some of the Java standard library functions assume they are defined) --> equals, toString. Good programming practice rule:  Every subclass should override the equals and toString methods defined in the superclass.
      1. equals compares two objects of the same class to see if they satisfy the intuitive definition of “being equal” and returns a Boolean value.  Recall that you cannot use == to determine object equality --> make calls to equals. In general, the method definition of equals is:  public boolean equals(ClassName ObjectName)
      2. toString returns a String value that represents the data in the object. In general, the method definition of toString is:  public String toString().
      3. See also the class Object notes below.

-      Constructors (superclass/subclass)

o   Reminder: Class constructor = A special class method (same name as the class) that executes automatically when an object of that class is created. Constructors are used to guarantee that the instance variables of the class initialize to specific values. A constructor typically serves to initialize instance variables in declaration.

o   The superclass may have constructors. The subclass can also have its own constructors. When we instantiate a subclass object, this object inherits the instance variables of the superclass, but the subclass object cannot directly access the private instance variables of the superclass.  The same is true for the methods of a subclass.  That is, the methods of the subclass cannot directly access the private members of the superclass. As a consequence, the constructors of the subclass can (directly) initialize only the instance variables of the subclass. Thus, when a subclass object is instantiated, to initialize the private instance variables it must also automatically execute one of the constructors of the superclass. A call to a constructor of the superclass is specified in the definition of a subclass constructor by using the reserved word super.

o   Defining constructors of the subclass --> Call to constructor of the superclass. The call to the superclass constructor must be the first statement in the subclass constructor and it must use super.

o   Once you write a constructor (that requires parameters) in the superclass, you must write constructors for the subclass as well. If not --> program errors. Why? Constructors aren't inherited.

-      Protected members of a class:

o   Reminder: As discussed earlier, private members of a class cannot be directly accessed outside the class (only method members of the class can access private members of the class) --> A subclass cannot directly access the private members of the superclass.

o   The problem: Sometimes it is necessary to give the subclass access to the private members of the superclass. How? If you allow a private member to become public, then anyone can access that member (unsafe direct access) --> not good!

o   Solution: A superclass could give access to a member to its subclass and still prevent its direct access outside the class, by declaring that member protected. The accessibility of a protected member of a class is somewhere between public and private. A subclass can directly access the protected members of the superclass.

o   Conclusion: If a subclass needs to access a member of the superclass, and the subclass also needs to prevent direct access of the member outside the class, the member of the superclass can be declared as protected.

o   Definition: If a method or instance variable is modified by protected (rather than public or private), then it can be accessed by name inside its own class definition, inside any subclass derived from it or in the definition of any class in the same package.

o   NOTE: The protected modifier provides very weak protection compared to the private modifier, because it allows direct access to any programmer who defines a suitable subclass. Therefore, instance variables should normally NOT be marked protected.

-      The class Object

o   In Java, if you define a class and do not use the reserved word extends to derive it from an existing class, then the class you define is automatically considered to be derived from the class Object --> In Java, every class is a subclass of the class Object This also means that the class Object is the superclass of every class in Java.  Being a superclass, every public member of the class Object can be overridden and/or can be invoked by every object of any class.

You must always use the reserved word super to use a method from the superclass in the subclass.

o   Every object of every class is of type Object, as well as being of the type of its own class.

o   NOTE: The class Object is in the package java.lang which is always imported automatically.

o   The class Object has some methods that every Java class inherits: equals and toString. Every object inherits these methods from some superclass. The superclass could be the class Object, or a class that inherited these methods (ultimately) from the class Object. As noted before,  these inherited methods should be overridden with definitions more appropriate to a given class.

o   NOTE: Some Java library classes assume that every class has its own version of such methods.

o   Having an Object class enables methods to be written with a parameter of type Object. A parameter of type Object can be replaced by an object of any class whatsoever. Example:

public boolean equals(Object obj) {
    if (obj instanceof Point) {
        Point otherPoint = (Point) obj;
        return (this.x == otherPoint.x && this.y == otherPoint.y);
    }
    else // not a Point object
        return false;
}

o   NOTE: To determine whether a reference variable that points to an object is of a particular class type, Java provides the operator instanceof.

o   Some explanations: Since the equals method is always inherited from the class Object, methods like the following simply overload it:

public boolean equals(Point otherPoint){
    . . .
}

However, this method should be overridden, not just overloaded:

public boolean equals(Object otherObject) {
    . . .
}

The overridden version of equals must meet the following conditions:

    • The parameter otherObject of type Object must be type cast to the given class (e.g., Point)
    • However, the new method should only do this if otherObject really is an object of that class, and if otherObject is not equal to null
    • Finally, it should compare each of the instance variables of both objects.

public boolean equals(Object obj){
    if(obj == null)
        return false;
    else if (obj instanceof Point) {//
        Point otherPoint = (Point) obj;
        return (this.x == otherPoint.x && this.y == otherPoint.y);
    }
    else // not a Point object
        return false;
}

  • The class Object has a small number of methods that make sense for all objects. The following are some constructors and methods of the class Object:

Method

Description

public Object()

default constructor

public String toString()

returns a String representation of the object.

public Boolean equals(Object obj)

compares 2 objects for equality

protected Object clone()

makes a (shallow) copy of the object and returns a reference to it

protected void finalize()

called by the garbage collector when objects go out of scope (destroyed)

public final Class<?> getClass()

returns the type of the object

notify(), notifyAll(), wait()

advanced methods for multithreaded programming

    • Because every Java class is a subclass of the class Object, it follows that the method toString becomes a public member of every Java class. Therefore, if a class does not override this method, whenever this method is invoked, the method’s default definition executes.
    • Because every Java class is a subclass of the class Object, it follows that the method equals becomes a public member of every Java class. Therefore, if a class does not override this method, whenever this method is invoked, the method’s default definition executes.
    • It is always a good idea to override the equals  and toString methods, even if it is not apparent in the design of the class that these methods will be of any use.  Both of these methods can be useful while debugging code.

Programming Samples:

Inheritance: Class Rectangle - Class Box

//Rectangle Class: superclass
//File Name: Rectangle.java
public class Rectangle {
  private double length;
  private double width;

  //superclass: default constructor
  public Rectangle()  {
    length = 0;
    width = 0;
  }

  //superclass: alternate constructor
  public Rectangle(double l, double w) {
    length = (l >= 0)? l: 0;
    width = (w >= 0)? w: 0;
    //set(l, w);
  }

  public void set(double l, double w)  {
    length = (l >= 0)? l: 0;
    width = (w >= 0)? w: 0;
  }

  public double getLength() {
    return length;
  }

  public double getWidth() {
    return width;
  }

  public double area() {
    return length * width;
  }

  public double perimeter() {
    return 2 * (length + width);
  }

  public void print() {
    System.out.print("Length = "  + length + "; Width = " + width);
  }

  public String toString() {
    return "Length = "  + length + "; Width = " + width;
  }

  public boolean equals(Rectangle r) {
    return length == r.length && width == r.width;
  }
}

//Box Class: subclass
//File Name: Box.java
public class Box extends Rectangle {
  private double height;

  //subclass default constructor
  public Box() {
    super();
    height = 0;
  }

  //subclass alternate constructor
  public Box(double l, double w, double h) {
    super(l, w);
    height = h;
  }

  //Method set: will overload same method from superclass
  public void set(double l, double w, double h){
    super.set(l, w);
    height = (h >= 0)? h: 0;
  }

  public double getHeight() {
    return height;
  }

  //Method area: will override same method from superclass
  public double area() {
    return  2 * (getLength() * getWidth() + getLength() * height + getWidth() * height);
  }

  public double volume() {
    return super.area() * height;
  }

  //Method print: will override same method from superclass
  public void print() {
    super.print();
    System.out.print("; Height = " + height);
  }

  //Method toString: will override same method from superclass
  public String toString() {
    return super.toString() + "; Height = " + height;
  }

  //Method equals: will overload same method from superclass
  public boolean equals(Box b) {
    //return getLength() == b.getLength() && getWidth() == b.getWidth() && height == b.height;
    //return super.equals(new Rectangle(b.getLength(), b.getWidth())) && height == b.height;
    return super.equals(b) && height == b.height;
    //the call to super works because b is an object of class Box, but also an object of class Rectangle
  }
}

//Client program
//Superclass: Rectangle
//Subclass: Box
//File Name: InheritRectangle.java
import java.util.Scanner;
public class InheritRectangle {
  public static void main(String[] args) {
    double ll, ww, hh; //user input - used in calls to set()
    Scanner input = new Scanner(System.in);
    Rectangle r1 = new Rectangle(); //superclass default constructor invoked
    Rectangle r2 = new Rectangle(15.8, 25.3); //superclass alternate constructor invoked
    Box b1 = new Box(); //subclass default constructor invoked
    Box b2 = new Box(10.75, 27.5, 37); //subclass alternate constructor invoked
    //Rectangle processing
    System.out.print("First rectangle: ");
    r1.print();
    System.out.println("\n\t\tPerimeter of first rectangle: " + r1.perimeter());
    System.out.println("\t\tArea of first rectangle: " + r1.area());
    System.out.print("Second rectangle: ");
    r2.print();
    System.out.println("\n\t\tPerimeter of second rectangle: " + r2.perimeter());
    System.out.println("\t\tArea of second rectangle: " + r2.area());
    System.out.print("Enter length and width for first rectangle: ");
    ll = input.nextDouble();
    ww = input.nextDouble();
    r1.set(ll, ww);
    System.out.print("First rectangle after call to set: ");
    r1.print();
    System.out.println("\n\t\tPerimeter of first rectangle after call to set: " + r1.perimeter());
    System.out.println("\t\tArea of first rectangle after call to set: " + r1.area());
    System.out.print("After call to equals(superclass): ");
    if (r1.equals(r2))
      System.out.println("The 2 rectangles have the same dimensions");
    else
      System.out.println("The 2 rectangles don't have the same dimensions");
    //Box processing
    System.out.print("\nFirst box: ");
    b1.print();
    System.out.println("\n\t\tArea of first box: " + b1.area());
    System.out.println("\t\tVolume of first box: " + b1.volume());
    System.out.print("Second box: ");
    b2.print();
    System.out.println("\n\t\tArea of second box: " + b2.area());
    System.out.println("\t\tVolume of second box: " + b2.volume());
    System.out.print("Enter length, width and height for first box: ");
    ll = input.nextDouble();
    ww = input.nextDouble();
    hh = input.nextDouble();
    b1.set(ll, ww, hh);
    System.out.print("First box after call to set: ");
    b1.print();
    System.out.println("\n\t\tArea of first box after call to set: " + b1.area());
    System.out.println("\t\tVolume of first box after call to set:  " + b1.volume());
    System.out.print("After call to equals(subclass): ");
    if (b1.equals(b2))
      System.out.println("The 2 boxes have the same dimensions");
    else
      System.out.println("The 2 boxes don't have the same dimensions");
  }
}

SAMPLE OUTPUT:
First rectangle: Length = 0.0; Width = 0.0
  Perimeter of first rectangle: 0.0
  Area of first rectangle: 0.0
Second rectangle: Length = 15.8; Width = 25.3
  Perimeter of second rectangle: 82.2
  Area of second rectangle: 399.74
Enter length and width for first rectangle: 15.8 25.3
First rectangle after call to set: Length = 15.8; Width = 25.3
  Perimeter of first rectangle after call to set: 82.2
  Area of first rectangle after call to set: 399.74
After call to equals(superclass): The 2 rectangles have the same dimensions

First box: Length = 0.0; Width = 0.0; Height = 0.0
  Area of first box: 0.0
  Volume of first box: 0.0
Second box: Length = 10.75; Width = 27.5; Height = 37.0
  Area of second box: 3421.75
  Volume of second box: 10938.125
Enter length, width and height for first box: 10 20 30
First box after call to set: Length = 10.0; Width = 20.0; Height = 30.0
  Area of first box after call to set: 2200.0
  Volume of first box after call to set:  6000.0
After call to equals(subclass): The 2 boxes don't have the same dimensions

Inheritance: Class Time - Class ExtendedTime

//Class Time: superclass
//File Name: Time.java
public class Time {
    private int hrs;
    private int mins;
    private int secs;

    //Default constructor
    public Time() {
       hrs = 0;
       mins = 0;
       secs = 0;
    }

    //Alternate constructor with parameters, to set the time
    public Time(int h, int m, int s) {
       hrs = h;
       mins = m;
       secs = s;
    }

    //Method to set the time
    public void setTime(int h, int m, int s) {
        hrs =  (h >= 0 && h < 24)? h : 0;
        mins = (m >= 0 && m < 60)? m : 0;
        secs = (s >= 0 && s < 60)? s : 0;
    }

    //Method to return the hours
    public int getHours() {
        return hrs;
    }

    //Method to return the minutes
    public int getMinutes(){
        return mins;
    }

    //Method to return the seconds
    public int getSeconds() {
        return secs;
    }

    //Method to print time in military format
    //Time is printed in the form HH:MM:SS
    public void printTimeMilitary(){
        System.out.print((hrs < 10? "0": "") + hrs + ":");
        System.out.print((mins < 10? "0": "") + mins + ":");
        System.out.print((secs < 10? "0": "") + secs);
    }

    //Method to print time in standard format
    //Time is printed in the form HH:MM:SS AM/PM
    public void printTimeStandard(){
        System.out.print((hrs == 0 || hrs == 12? 12: hrs % 12) + ":");
        System.out.print((mins < 10? "0": "") + mins + ":");
        System.out.print((secs < 10? "0": "") + secs + " ");
        System.out.print((hrs < 12? "AM": "PM"));
    }

    //Method toString
    public String toString(){
         return hrs + ":" + mins + ":" + secs;
    }

    //Time advanced by one hour.
    public void incrementHrs() {
        hrs++;
        if(hrs > 23)
            hrs = 0;
    }

    //Time advanced by one minute.
    public void incrementMins() {
        mins++;
        if(mins > 59){
            mins = 0; //next: call incrementHrs() OR:
            hrs++;

            if(hrs > 23)
                hrs = 0;
        }
    }

    //Time advanced by one second. When 23:59:59 wrap around to 00:00:00
    public void incrementSecs(){
        secs++;
        if(secs > 59){
            secs = 0; //next: call incrementmins() OR:
            mins++;
            if(mins > 59){
                mins = 0;
                hrs++;
                if(hrs > 23)
                    hrs = 0;
            }
        }
    }

    //Method to compare two times for equality
    public boolean equals(Time otherTime) {
        return (hrs == otherTime.hrs && mins == otherTime.mins && secs == otherTime.secs);
    }

    //Method to compare two times for less than
    public boolean lessThan(Time t) {
        return (hrs < t.hrs || hrs == t.hrs && mins < t.mins || hrs == t.hrs && mins == t.mins && secs < t.secs);
    }

     //Method to copy the time
    public void copy(Time otherTime) {
        hrs = otherTime.hrs;
        mins = otherTime.mins;
        secs = otherTime.secs;
    }

    //Method to return a copy of the time
    public Time getCopy() {
        return new Time(hrs, mins, secs);

    }
}

//Class ExtendedTime: subclass
//File Name: ExtendedTime.java
public class ExtendedTime extends Time {
    private String  zone; //added data member

    //Default constructor
    public ExtendedTime() {
        super();
        zone  =  "EST" ;
    }

    //Alternate constructor
    public ExtendedTime(int h, int m, int s, String z) {
        super(h, m, s);
        zone  =  z ;
    }

    public void setTime(int h, int m, int s, String z) {
        super.setTime(h, m, s);
        zone = z;
    }

    public String toString(){
        return ("The extended time is: " + super.toString() + " " + zone);
    }

    public String getZone(){
        return zone;
    }

    public void printTimeMilitary(){
        super.printTimeMilitary();
        System.out.println(" (" + zone  + ")");
    }

    public void printTimeStandard(){
        super.printTimeStandard();
        System.out.println(" (" + zone  + ")");
    }

    public void copy(ExtendedTime otherTime) {
        super.copy(otherTime);
        zone = otherTime.zone;
    }

    public ExtendedTime getCopy() {
       return new ExtendedTime(super.getHours(), super.getMinutes(), super.getSeconds(), zone);
    }

    public boolean equals(ExtendedTime otherTime) {
        return super.equals(otherTime) && zone.equals(otherTime.zone);
    }
 
    public boolean lessThan(ExtendedTime t) {
       return zone.equals(t.zone) && super.lessThan(t);
    }
}

//Client program for Time/ExtendedTime
//File Name: ClientExtTime.java
import java.util.Scanner;
public class ClientExtTime {

    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        ExtendedTime t1 = new ExtendedTime(9, 45, 35, "CST");
        ExtendedTime t2 = new ExtendedTime();
        int hours, minutes, seconds;
        String z;
        System.out.println(t1); //toString from subclass
        System.out.println(t2); //toString from subclass

        System.out.print("Initial time t1 (alternate constructor invoked) - military format: ");
        t1.printTimeMilitary();
        System.out.print("Initial time t1 (alternate constructor invoked) - standard format: ");
        t1.printTimeStandard();

        System.out.print("Initial time t2 (default constructor invoked) - military format: ");
        t2.printTimeMilitary();
        System.out.print("Initial time t2 (default constructor invoked) - standard format: ");
        t2.printTimeStandard();

        t2.setTime(9, 45, 35);
        System.out.print("t2 after call to setTime - military format: ");
        t2.printTimeMilitary();
        System.out.print("t2 after call to setTime - standard format: ");
        t2.printTimeStandard();

        if (t1.equals(t2))
            System.out.println("After call to equals: times are equal.");
        else
            System.out.println("After call to equals: times are NOT equal.");

        if (t1.lessThan(t2))
            System.out.println("After call to lessThan: t1 is less than t2.");
        else
            System.out.println("After call to lessThan: t1 is NOT less than t2.");

        System.out.print("Enter hours, minutes, and seconds (Pacific Standard Time): ");

        //consider calling a method to do input validation
        hours = input.nextInt();
        minutes = input.nextInt();
        seconds = input.nextInt();

        z = "PST";
        t1.setTime(hours, minutes, seconds, z);
        System.out.print("New time t1 after call to setTime - standard format, Pacific: ");
        t1.printTimeStandard();

        z = "CST";
        t1.setTime(hours + 1, minutes, seconds, z);
        //OR: t1.incrementHrs();
        System.out.print("New time t1 after call to incrementHrs - standard format, Central: ");
        t1.printTimeStandard();

        z = "EST";
        //t1.setTime(hours + 2, minutes, seconds, z);
        t1.incrementHrs();
        System.out.print("New time t1 after call to incrementHrs - standard format, East: ");
        t1.printTimeStandard();

        t2 = t1.getCopy();

  // OR: t2.copy(t1);

        System.out.print("New t2 after call to copy - standard format: ");
        t2.printTimeStandard();
        System.out.println("Test toString for t2: " + t2);
     }
}
SAMPLE OUTPUT:
The extended time is: 9:45:35 CST
The extended time is: 0:0:0 EST
Initial time t1 (alternate constructor invoked) - military format: 09:45:35 (CST)
Initial time t1 (alternate constructor invoked) - standard format: 9:45:35 AM (CST)
Initial time t2 (default constructor invoked) - military format: 00:00:00 (EST)
Initial time t2 (default constructor invoked) - standard format: 12:00:00 AM (EST)
t2 after call to setTime - military format: 09:45:35 (EST)
t2 after call to setTime - standard format: 9:45:35 AM (EST)
After call to equals: times are NOT equal.
After call to lessThan: t1 is NOT less than t2.
Enter hours, minutes, and seconds (Pacific Standard Time): 10 11 12
New time t1 after call to setTime - standard format, Pacific: 10:11:12 AM (PST)
New time t1 after call to incrementHrs - standard format, Central: 11:11:12 AM (CST)
New time t1 after call to incrementHrs - standard format, East: 12:11:12 PM (EST)
New t2 after call to copy - standard format: 12:11:12 PM (EST)
Test toString for t2: The extended time is: 12:11:12 EST

Base class: Existing class; same as superclass.
Derived class: New class created from existing class; same as subclass.
Inheritance: A way to define a new class based on a class that already exists. Relating two or more classes with the ”is-a” relationship between them.
Multiple inheritance: The subclass is derived from more than one superclass. Not supported in Java.
Overriding: Declaring a method in a subclass with the same signature as a method in its superclass.
Overloading: Declaring a method with the same name, different parameters.
Single inheritance: The subclass is derived from only one existing superclass.
Subclass: New class created from an existing class; same as derived class.
Superclass: Existing class; same as base class.
super: (keyword) The reference used by a subclass to call an overridden method.

Additional Resources:
1. (Sun) API specification for version 6 of the Java™ Platform, Standard Edition (Class Object): http://java.sun.com/javase/6/docs/api/
2. (Sun) The Java Tutorials, Inheritance: http://java.sun.com/docs/books/tutorial/java/IandI/subclasses.html

References:
[1] Java Programming: From Problem Analysis to Program Design, by D.S. Malik, Thomson Course Technology, 2008
[2] Building Java Programs
: A Back to Basics Approach, by Stuart Reges, and Marty Stepp, Addison Wesley, 2008.