INHERITANCE Spring 2019
INHERITANCE BASICS Inheritance is a technique that allows one class to be derived from another A derived class inherits all of the data and methods from the original class Suppose that class Y is inherited from class X class X is the superclass, also known as the base class or the parent class class Y is the subclass, also known as the derived class, child class, or extended class class Y consists of everything created in class Y, as well as everything from class X, which it inherits In Java, each class can only directly inherit from one class
DECLARING A SUBCLASS Use the keyword extends to declare the derived class Examples: // Example 1 public class AAA {... } // AAA is the base class public class BBB extends AAA // BBB is the derived class {... } // Example 2 public class Employee {...} // base class public class HourlyEmployee extends Employee {... } // derived
DEALING WITH PARENT CLASS When you create a derived object, the derived class may need to access parent class methods. This is done with the keyword super Like this, super has two usage cases The first usage of the keyword is when the derived class constructor needs to invoke the base class constructor In this case, super acts as the call to the base class constructor The call to super() must be the first line of the derived class constructor // invokes base class default constructor super(); // invokes base class constructor with parameters super(parameters);
DEALING WITH PARENT CLASS Example: // Example, for a class called HourlyEmployee, derived from // Employee public class HourlyEmployee extends Employee { public HourlyEmployee() // default constructor { super(); // invokes Employee() constructor } public HourlyEmployee(double h, double r) { super(h,r); // invokes Employee constructor w/ 2 parameters } //... more methods and data } // end class HourlyEmployee
DEALING WITH PARENT CLASS If an explicit call to the parent constructor is not made, the subclass s constructor will automatically invoke the default constructor of the base class at the beginning of the constructor. Can also use super to invoke a method from the parent class (from inside the derived class). Format: super.method(parameters)
PROTECTED Recall that public data and methods can be accessed by anyone and private data and methods can only be accessed by the class that they are in Like in C++, protected data and methods of a public class can be accessed by any classes derived from said class In Java, a protected member can also be accessed by any class in the same package
FINAL In addition to creating constant variable identifiers, the keyword final can be used for a couple of special purposes involving inheritance When used on a class declaration, it means that the class cannot be extended (cannot become a parent class) When used on a method declaration, it means that the method cannot be overridden in a subclass (the final version of the method)
METHOD OVERRIDING Although the derived class inherits all methods from the bass class, it is still possible to create a method in the derived class with the same signature as one in the base class All methods are similar to virtual functions in C++ As an example, suppose a class Rectangle is derived from class Shape Shape has a method with this signature: void Draw() We can define a method in class Rectangle with the same signature. The derived version will override the base class version when called through an object of type Rectangle Rectangle r = new Rectangle(); //Creates a Rectangle object r.draw(); //Invokes the Draw method from the Rectangle class Note that the Rectangle class Draw() method can still invoke the method from Shape by using the keyword super public void Draw() { super.draw(); //invoke parent s Draw() //Continue with method }
@OVERRIDE Java has something called annotations that can help you as a programmer to prevent problems by forcing the compiler to flag certain situations One of the more common annotations is @Override When a method is preceded by @Override, the compiler will generate an error if the method does NOT override a superclass/interface method This can be used to help make sure you have the right signature and that nothing has changed in the original declaration, so it is a good idea to use this Imagine the previous example with Rectangle and Shape, if you wished to override the Draw() method in the Rectangle class, it would be a good idea to do it like this: @Override public void Draw() { //Method Body }
ABSTRACT CLASSES Superclasses are more general than subclasses Sometimes it does not make sense to actually instantiate a base class Such a class is primarily a grouping for common data and behaviors of subclasses an abstract class To make a class abstract, use the modifier abstract public abstract class Shape Now that Shape is abstract, this would be illegal: Shape s = new Shape(); Specifically, it s the call to new Shape() that is illegal
ABSTRACT METHODS Methods can also be abstract An abstract method is a method signature without a definition Abstract methods can only be created inside abstract classes The main purpose of an abstract method is to be overridden in derived classes (with the same signature) Example: // Shape is an abstract class public abstract class Shape { public abstract double findarea(); // findarea is an abstract method // other methods and data }
THE OBJECT CLASS In Java, every class is derived from a class called Object If no specific inheritance is declared for a class, it automatically has Object as a superclass There are several methods in class Object, we are going to look at three in particular (remember, these are inherited by every Java class) public Boolean equals(object object) public String tostring() public Object clone()
EQUALS Tests whether two objects are equal object1.equals(object2) //returns true if equal, false if not Default implementation is public Boolean equals(object obj) { return (this == obj); } Note that the default implementation is equivalent to ==, as it only tests the reference variables for equality. The intent is that subclasses should override the equals method whenever they want a test of equality for the contents of two objects.
TOSTRING This returns a string that represents the object objectname.tostring() The default version is not always useful (it returns a string that contains the class name and a hash code for the object), but this can be overridden in any derived class. This method is invoked when an object is passed where a String is expected (System.out.print or concatenation, for example) As an example, for a class called Fraction, you might have: public String tostring() { return numerator + "/" + denominator; } Assuming the above function, this illustrates its usage: Fraction f1 = new Fraction(4,5); // create the fraction 4/5 System.out.print(f1.toString()); // will print "4/5" System.out.print(f1); // also prints "4/5" as this // always invokes the tostring method of a class
CLONE Remember, direct assignment between object names will only copy one reference variable to another. The clone() method can make copies of objects newobject = someobject.clone(); Not all objects can be cloned. Only objects that implement the java.lang.cloneable interface (which will be discussed later) can use the clone method The default clone() method from the object class does a shallow copy. If a deep copy is needed, you should override clone() for a class
OTHER METHODS FROM OBJECT Class Object has some other methods, such as finalize called by garbage collector to perform cleanup on an object, rarely overridden. As of Java 9, this method has been deprecated, so it should be avoided. getclass returns an object of type Class, with information about the calling object s type hashcode returns a hash value that can be used as a key for the object notify, notifyall, wait related to multithreading
LOCAL VARIABLE TYPE INFERENCE In Java 10, Java added local variable type inference by using the var keyword This keyword can only be used for local variables that have an initializer CANNOT be used with member data CANNOT be used with parameters CANNOT be used with uninitialized local variables If the type is not explicitly inferable, you CANNOT use this (for example, a variable initialized with null) In that case (and only that case) you may use var instead of the type Because the variable is being initialized immediately, the compiler can easily determine the type Java is still a statically typed language, since the compiler is inferring the type and replacing var with that type upon compilation
LOCAL VARIABLE TYPE INFERENCE This was mainly introduced to make code more concise Also has the benefit of only having to change a type in one place Some examples: //LEGAL creates a StringBuilder variable var sb = new StringBuilder(); //LEGAL creates a double variable var d = 12.51; //ILLEGAL not initialized on the same line var i; i = 5; //This line would be much less concise without the use of var var map1 = new ConcurrentSkipListMap<MyKeyType,MyValueType>();
EXAMPLES Default operation of equals and tostring uses a Fraction class Overriding equals and tostring in the Fraction class Deitel Inheritance Examples (Chapter 9)