Professional Documents
Culture Documents
Recapitulation:
Inheritance is a reusability mechanism in object-oriented programming in which the common
properties of various objects are exploited to form relationships with each other. The abstract and
common properties are provided in the superclass, which is available to the more specialized
subclasses. For example, a color printer and a black-and-white printer are kinds of a printer (single
inheritance); an all-in-one printer is a printer, scanner, and photocopier (multiple inheritance). It
should be noted that Java does not support multiple inheritance but does support multiple-interface
inheritance
When we say that a class B is inherited from another class A, then class B is referred to as a
derived class (or subclass) and class A is called as a base class (or superclass). By inheritance,
the derived class receives the behaviour of the base class, such that all the visible member
methods and variables of the base class are available in the derived class. Apart from the inherited
behavior, the derived class specializes its behavior by adding to or overriding base class behavior.
Inheritance is a powerful feature that allows new classes to be derived from existing ones.
The derived class inherits the interface of the base class and can add new methods or
change existing ones to suit its purpose. Any number of classes can be added to an
inheritance scheme to produce a hierarchy (the collection of all classes extending from a
common super class) of related types. The Java implementation of inheritance supports
polymorphism, which allows objects of different types to be treated as if they were of the
same type.
Inheritance provides a mechanism for new classes to use the data and methods of the
existing classes. For example if a manager is an object with a name, a salary, a hire date
and a secretary name, then class Manager can inherit the name, hire date and salary
structure from the Employee class and just add a new private field for the secretaryName
data. Inheritance is effected using the keyword, “extends” for example:
}
Class Manager inherits all the data and methods of class Employee. The existing class is
termed the superclass, base class, or parent class and the new class is called the subclass,
derived class or child class. So Employee contains the set of all Managers or Employee is
a superset of the set of Managers.
We need constructor methods for our new class Manager. We might propose the
following constructor:
But this does not compile because name and salary are private data of class Employee. A
subclass has no rights of access to the private data of a super class. Like any other class
the subclass can only access private data through the interface provided in this case we
need to use the constructor methods of class Employee. A subclass refers to the super
class using the keyword “super”. Accordingly, we can write the constructor as follows:
public Manager(String aName, double aSalary, String aSecretaryName, int year, int
month, int day)
{ super(aName, aSalary, year, month, day);
secretaryName = aSecretaryName;
When used to reference a superclass constructor the keyword super must be the first
statement in the method.
The order and types of actual parameters MUST correspond to the order and types of
formal parameters for the super class constructor.
We could write the default constructor for the Manager class similarly:
public Manager()
{
super();
secretaryName = “”;
}
In fact we do not need to include the reference to the super class’s default constructor as
the compiler will automatically include this for us.
Subclasses inherit all the data and methods of their super classes. For example, a
Manager object inherits the print() method of the Employee class:
Methods with the same signature may exist at all levels of the inheritance hierarchy (but
not in the same file); methods in the subclass simply hide or shadow or override those in
the super classes. But subclass and super class cannot have methods with the same
signature but different return types.
Polymorphism
Recapitulation:
The Greek roots of the term polymorphism refer to the “several forms” of an
entity. In the real world, every message you communicate has a context.
Depending on the context, the meaning of the message may change and so may
the response to the message. Similarly in OOP, a message can be interpreted in
multiple ways (polymorphism), depending on the object.
Let’s assume that you have a method named show() in a base class. The show()
method returns the details of an object. Hence, show() is implemented
(overridden) in all the derived classes of base class. A base class reference can
point to any derived class object. When you call the show() method from the
base class reference, it results in calling the show() method of the actual object
type (i.e. the dynamic type of the object). This dynamic behaviour is known as
runtime polymorphism.
Note 1:
• Overload resolution takes place entirely at compile time.
• You cannot overload methods with the methods differing in return types
alone.
The is-a principle states that objects of a subclass are also members(objects) of the supper
class, by definition. Accordingly, we can always assign an object of the subclass to a
variable of the super class hence, object variables in Java are polymorphic. No explicit
cast is required because the relationship is implicit in the inheritance hierarchy. For
example, if class Manager extends class Employee then an Employee variable can store
an Employee object or a Manager object. If a method is invoked on a superclass variable,
the system determines which class of object the variable actually contains and calls the
appropriate method for objects of that class:
the system automatically selects the correct print() method for either Employee or
Manager objects. The system selects the appropriate method to use at run-time, not at
compile-time:
Employee e;
System.out.print(“Store e1 or m1 in e ?”);
String answer = in.readLine();
if (answer.equals(“e1”))
{
e = e1;
True polymorphism can be distinguished from simple overloading where several methods
with the same name are distinguished by having different argument lists. Overloading,
termed ad hoc polymorphism is implemented using static binding at compile time. For
example, the constructors Employee() and Employee(String name, double salary)
overload the name Employee. Calls to these methods are easily distinguished at compile
time by simply matching the parameter list of the caller and the method.
Note 2:
The overriding method
• Should have the same argument list types (or compatible types) as the base
version.
• Should have the same return type.
• But from Java 5 onwards, the return type can be a subclass–covariant return types.
• Should not have a more restrictive access modifier than the base version.
o But it may have a less restrictive access modifier.
• Should not throw new or broader checked exceptions.
o But it may throw fewer or narrower checked exceptions, or any unchecked
exception.
• The names should exactly match
Remember that you cannot override a method if you do not inherit it. Private methods
cannot be overridden because they are not inherited.
If the name or signature of the base class method and the overriding method don’t match,
you will cause subtle bugs. So ensure that they are exactly the same.
In order to overcome the subtle problems of overloading, you can use @Override
annotation, which was introduced in Java 5. This annotation explicitly expresses to the
The JVM keeps track of the actual class of objects stored in object variables in order to
implement polymorphism. The actual class name is accessible to the programmer using
the getClass().getName() method.
both staff[0] and m1 refer to the same object but staff[0] is considered to be only an
employee object by the compiler. This means that you can call
m1.getSecretaryName(); // ok
staff[0].getSecretaryName();// error
The declared type of staff[0] is Employee and the getSecretaryName() method is not a
method of the Employee class. Take note that the getSecretaryName() method is not
defined in the super class.
such that staff[0] and managers[0] are the same reference. Can we call
managers[0].getSecretaryName();
Which will try to access a nonexistent field which would corrupt neighbouring memory.
Access Modifiers/Specifiers
Access modifiers determine the level of visibility (and therefore access) for a Java entity
(a class, method, or field).
Access modifiers enable you to enforce effective encapsulation. If all member variables
of a class can be accessed from anywhere, then there is no point putting these variables in
a class and no purpose in encapsulating data and methods together in a class.
Private methods are desirable where you wish to break up the code for a computation into
separate helper methods.
Java also provides the protected access modifier: protected data or methods in a class can
be accessed by subclasses. Any class that extends a class with protected data or methods
can access the data and methods as though they were public. Although this is seemingly
an attractive idea, in practice this is problematic because once protected access provided
it cannot be easily withdrawn because users may write subclasses whose code depends on
this access. It is always a bad idea to give class data protected access because this breaks
encapsulation and you cannot change the implementation later in case the class has been
extended and the protected data accessed by new subclasses. Rather provide an accessor
method and give this protected access to preserve encapsulation.
What is the difference between protected and default access? One significant difference
between these two access modifiers arises when we talk about a subclass belonging to
another package than its superclass. In this case, protected members are accessible in the
subclass, whereas default members are not.
For example, if salary data for Employee is declared as protected it is accessible in all its
subclasses like Manager. If Manager belongs to yet another package, all the protected
methods and data will be accessible but data and methods with default access specifier
are not accessible in other packages.
Final access
We can prevent users from deriving subclasses from existing classes by declaring them as
final (eg public final class Employee). We can also make a specific method in a class
final so that no other method can override it. All methods of a final class are
automatically final.
Programs which attempt to extend final classes compile but will fail at run-time.
Many Java system classes are final, for example class String and the wrapper classes
(Integer, Double and Boolean)
Final instance variables or fields cannot be changed after initialised when object is
constructed eg private final String name; they are useful for fields whose type is primitive
or an immutable class.
Note that when a class is declared as final, only methods not fields are automatically
final.
It is important to note that a class (or interface) cannot be declared as private or protected.
Furthermore, member methods or fields of an interface cannot be declared as private or
protected.
Static fields are called class variables or fields and there is only one such field per class.
Are declared as: private static int number; static variables are rare but
static constants are common eg PI in the Math class:
public static final PI=3.14159265389...
and is accessed as Math.PI
static methods do not operate on objects eg pow() in the Math class is a static method.
Because static methods don’t operate on objects, you cannot access instance fields from
static methods. But static methods can access the static fields in their class here is an
example of such a static method:
public static int getNextId()
{
return nextID // returns a static field