Module 3 Voop
Module 3 Voop
PROGRAMMING WITH
JAVA
Department of Computer Science & Engineering
www.cambridge.edu.in
Object-Oriented Programming : The Three OOP Principles -
Inheritence
• Inheritance is the process by which one object acquires the properties of another object.
• Inheritance interacts with encapsulation as well. If a given class encapsulates some attributes, then any
subclass will have the same attributes plus any that it adds as part of its specialization (see Figure 2-2).
• A new subclass inherits all of the attributes of all of its ancestors.
Inheritance
• Inheritance is one of the cornerstones of object-oriented programming offering benefits like code extensibility
(Extensibility is a measure of the ability to extend a system through the addition of new functionality or
through modification of existing functionality) and code reusability (Code reuse is the practice of using existing
code for a new function or software).
• Using inheritance, we can create a general class that defines traits common to a set of related items. This class
can then be inherited by other, more specific classes, each adding those things that are unique to it.
• In the terminology of Java, a class that is inherited is called a superclass (parent class or base class).
• The class that does the inheriting is called a subclass(child class or inherited class). Therefore, a subclass is a
specialized version of a superclass. It inherits all of the instance variables and methods defined by the superclass
and adds its own elements.
Inheritance Basics
• To inherit a class, we simply incorporate the definition of one class into another by using the extends keyword.
• The following program creates a superclass called A and a subclass called B.
Inheritance -
class Demo
Example {
public static void main(String args[])
// Create a superclass. {
class A A superob = new A();
{ B subob = new B();
int i, j; superob.i = 10;
void showij( ) superob.j = 20;
{ System.out.println("Contents of superob: ");
System.out.println("i and j: " + i + " " + j); superob.showij();
} subob.i = 7;
} subob.j = 8;
// Create a subclass by extending class A. subob.k = 9;
class B extends A System.out.println("Contents of subob: ");
{ subob.showij();
int k; subob.showk();
void showk( ) System.out.println("Sum of i, j and k in subob:");
{ subob.sum();
System.out.println("k: " + k); }
} }
void sum()
{
System.out.println("i+j+k: " + (i+j+k));
}
}
Inheritance - We can only specify
one superclass for any
• A reference variable of a superclass can be assigned a reference to any subclass derived from that superclass.
class RefDemo
{
public static void main(String args[ ])
{ Volume of weightbox is 105.0
BoxWeight weightbox = new BoxWeight(3, 5, 7, 8.37); Weight of weightbox is 8.37
Box plainbox = new Box( ); Volume of plainbox is 105.0
double vol;
vol = weightbox.volume( );
System.out.println("Volume of weightbox is " + vol);
System.out.println("Weight of weightbox is " +weightbox.weight);
// assign BoxWeight reference to Box reference
plainbox = weightbox; // all dogs are animals
vol = plainbox.volume( ); // OK, volume() defined in Box
System.out.println("Volume of plainbox is " + vol);
/* The following statement is invalid because plainbox does not define a weight member. */
// System.out.println("Weight of plainbox is " + plainbox.weight);
}
}
A superclass can reference a subclass object
• Here, weightbox is a reference to BoxWeight objects, and plainbox is a reference to Box objects.
• Since BoxWeight is a subclass of Box, it is permissible to assign plainbox a reference to the weightbox object.
• It is important to understand that it is the type of the reference variable—not the type of the object that it refers
to—that determines what members can be accessed.
• That is, when a reference to a subclass object is assigned to a superclass reference variable, we will have access
only to those parts of the object defined by the superclass.
• This is why plainbox can’t access weight even when it refers to a BoxWeight object. If we think about it,
this makes sense, because the superclass has no knowledge of what a subclass adds to it.
• This is why the last line of code in the preceding fragment is commented out. It is not possible for a Box
reference to access the weight field, because Box does not define one.
Using super
• The constructor for BoxWeight explicitly (in the previous example) initializes the width, height, and depth
fields of Box( ).
• Not only does this duplicate code found in its superclass, which is inefficient, but it implies that a subclass must
be granted access to these members.
• However, there will be times when we will want to create a superclass that keeps the details of its
implementation to itself.
• In this case, there would be no way for a subclass to directly access or initialize these variables on its own.
• Whenever a subclass needs to refer to its immediate superclass, it can do so by use of the keyword super.
• super is a reference variable that is used to refer to the immediate superclass.
super has two general forms.
1) The first calls the superclass constructor.
2) Used to access a member of the superclass that has been hidden by a member of a subclass.
Using super – (1) Using super to Call Superclass Constructors
• A subclass can call a constructor defined by its superclass by use of the following form of super:
super(arg-list);
• Here, arg-list specifies any arguments needed by the constructor in the superclass.
• super( )must always be the first statement executed inside a subclass’ constructor.
• To see how super( ) is used, consider this improved version of the BoxWeight( ) class:
class BoxWeight extends Box
{
double weight;
BoxWeight(double w, double h, double d, double m)
{
super(w, h, d);
weight = m;
}
}
Using super – (1) Using super to Call Superclass parameterless
class A
{
Constructors class Demo
{
int i, j; public static void main(String args[])
A()
{
{
i=10; B subob = new B();
j=20; subob.showij();
} subob.showk();
void showij( ) System.out.println("Sum of i, j and k in subob:");
{ subob.sum();
System.out.println("i and j: " + i + " " + j); }
}
}
}
class B extends A
{
int k;
B()
{
super();
k=20; i and j: 10 20
}
void showk( ) k: 20
{ Sum of i, j and k in subob:
System.out.println("k: " + k); i+j+k: 50
}
void sum()
{
System.out.println("i+j+k: " + (i+j+k));
}
}
Using super – (1) Using super to Call Superclass Constructors with paramaters
class A class Demo
{ {
int i, j; public static void main(String args[])
A(int x,int y)
{
{
i=x; B subob = new B(10,20,30);
j=y; subob.showij();
} subob.showk();
void showij( ) System.out.println("Sum of i, j and k in subob:");
{ subob.sum();
System.out.println("i and j: " + i + " " + j); }
}
}
}
class B extends A
{
int k;
B(int x,int y,int z)
{
super(x,y);
k=z; i and j: 10 20
}
void showk( ) k: 30
{ Sum of i, j and k in subob:
System.out.println("k: " + k); i+j+k: 60
}
void sum()
{
System.out.println("i+j+k: " + (i+j+k));
}
}
Using super to Call Superclass Constructors
• Here, BoxWeight( ) calls super( ) with the arguments w, h, and d. This causes the Box( )
constructor to be called, which initializes width, height, and depth using these values.
• BoxWeight no longer initializes these values itself. It only needs to initialize the value unique
to it: weight. This leaves Box free to make these values private if desired.
• In the preceding example, super( ) was called with three arguments.
• Since constructors can be overloaded, super( ) can be called using any form defined by the
superclass.
• The constructor executed will be the one that matches the arguments.
• When a subclass calls super( ), it is calling the constructor of its immediate superclass.
• Thus, super( ) always refers to the superclass immediately above the calling class. This is
true even in a multileveled hierarchy.
Using super – The Second use of super keyword
A Second Use for super
• The second form of super acts somewhat like this, except that it always refers to the
superclass of the subclass in which it is used. This usage has the following general form:
super.member
}
} Inside C's constructor
• It makes sense that constructors complete their execution in order of
derivation.
• Because a superclass has no knowledge of any subclass, any
initialization it needs to perform is separate from and possibly
prerequisite to any initialization performed by the subclass.
• Therefore, it must complete its execution first.
Method Overriding
• when a method in a subclass has the same name and type signature as
a method in its superclass, then the method in the subclass is said
to override the method in the superclass.
• When an overridden method is called from within its subclass, it will
always refer to the version of that method defined by the subclass.
class A {
int i, j;
A(int a, int b) {
i = a;
j = b;
}
// display i and j
void show() {
System.out.println("i and j: " + i + " " + j);
}
}
class B extends A {
int k;
B(int a, int b, int c) {
super(a, b);
k = c;
}
// display k – this overrides show() in A
void show() {
System.out.println("k: " + k);
}
}
class Override {
public static void main(String args[]) {
B subOb = new B(1, 2, 3);
subOb.show(); // this calls show() in B
}
}
• When show( ) is invoked on an object of type B, the version of show(
) defined within B is used.
• That is, the version of show( ) insideB overrides the version declared
in A.
• Method overriding occurs only when the names and the type
signatures of the two methods are identical.
• If they are not, then the two methods are simply overloaded.
Dynamic Method Dispatch
• Dynamic method dispatch is the mechanism by which a call to an
overridden method is resolved at run time, rather than compile time.
• Dynamic method dispatch is important because this is how Java
implements run-time polymorphism.
class A {
void callme() {
System.out.println("Inside A's callme method");
}
}
class B extends A { // override callme()
void callme() {
System.out.println("Inside B's callme method");
}
}
class C extends A { // override callme()
void callme() {
System.out.println("Inside C's callme method");
}
}
class Dispatch {
public static void main(String args[]) {
A a = new A(); // object of type A
B b = new B(); // object of type B
C c = new C(); // object of type C
A r; // obtain a reference of type A
r = a; // r refers to an A object
r.callme(); // calls A's version of callme
r = b; // r refers to a B object
r.callme(); // calls B's version of callme
r = c; // r refers to a C object
r.callme(); // calls C's version of callme
}
}
• This program creates one superclass called A and two subclasses of it,
called B and C.
• Subclasses B and C override callme( )declared in A.
• Inside the main( ) method, objects of type A, B, and C are declared.
• Also, a reference of type A, called r, is declared.
• The program then in turn assigns a reference to each type of object
to r and uses that reference to invoke callme( ).
• As the output shows, the version of callme( ) executed is determined
by the type of object being referred to at the time of the call.
• Had it been determined by the type of the reference variable, r, you
would see three calls to A’s callme( ) method.
Why Overridden Methods?
• Overridden methods allow Java to support run-time polymorphism.
• Polymorphism is essential to object-oriented programming for one
reason: it allows a general class to specify methods that will be
common to all of its derivatives, while allowing subclasses to define
the specific implementation of some or all of those methods.
• Overridden methods are another way that Java implements the “one
interface, multiple methods” aspect of polymorphism.
• Polymorphism is understanding that the superclasses and subclasses
form a hierarchy which moves from lesser to greater specialization.
• Used correctly, the superclass provides all elements that a subclass
can use directly.
• It also defines those methods that the derived class must implement
on its own.
• This allows the subclass the flexibility to define its own methods, yet
still enforces a consistent interface.
• Thus, by combining inheritance with overridden methods, a
superclass can define the general form of the methods that will be
used by all of its subclasses.
Using Abstract Classes
• There are situations in which you will want to define a superclass that
declares the structure of a given abstraction without providing a
complete implementation of every method.
• That is, sometimes you will want to create a superclass that only
defines a generalized form that will be shared by all of its subclasses,
leaving it to each subclass to fill in the details.
• Such a class determines the nature of the methods that the subclasses
must implement.
• One way this situation can occur is when a superclass is unable to
create a meaningful implementation for a method.
• Consider the class Triangle. It has no meaning if area( ) is not
defined.
• In this case, you want some way to ensure that a subclass does,
indeed, override all necessary methods.
• Java’s solution to this problem is the abstract method.
• we can require that certain methods be overridden by subclasses by
specifying the abstract type modifier.
• These methods are sometimes referred to as subclasser
responsibility because they have no implementation specified in the
superclass.
• Thus, a subclass must override them—it cannot simply use the
version defined in the superclass. To declare an abstract method, use
this general form:
• abstract type name(parameter-list);
• Any class that contains one or more abstract methods must also be
declared abstract.
• To declare a class abstract, you simply use the abstract keyword in
front of the class keyword at the beginning of the class declaration.
• There can be no objects of an abstract class. That is, an abstract class
cannot be directly instantiated(CREATED) with the new operator.
• Such objects would be useless, because an abstract class is not fully
defined.
• Also, you cannot declare abstract constructors, or abstract static
methods.
• Any subclass of an abstract class must either implement all of the
abstract methods in the superclass, or be declared abstract itself.
abstract class A {
abstract void callme();
// concrete methods are still allowed in abstract
void callmetoo() {
System.out.println("This is a concrete method.");
}
}
class B extends A {
@Override
void callme() {
System.out.println("B's implementation of callme.");
}
}
class AbstractDemo {
public static void main(String args[])
{ B's implementation of callme.
B b = new B();
b.callme(); This is a concrete method.
b.callmetoo();
}
}
• Notice that no objects of class A are declared in the program. As
mentioned, it is not possible to instantiate an abstract class.
• One other point: class A implements a concrete method
called callmetoo( ).
• This is perfectly acceptable. Abstract classes can include as much
implementation as they see fit.
• It is no longer possible to declare objects of type Figure, since it
is now abstract.
• And, all subclasses of Figure must override area( ).
• To prove this to yourself, try creating a subclass that does not
override area( ). You will receive a compile-time error.
• It is not possible to create an object of type Figure, you can create
a reference variable of type Figure.
• The variable figref is declared as a reference to Figure, which
means that it can be used to refer to an object of any class derived
from Figure.
• As explained, it is through superclass reference variables that
overridden methods are resolved at run time.
Using final with Inheritance
• The keyword final has three uses.
• First, it can be used to create the equivalent of a named constant(next).
• Second, Using final to Prevent Overriding.
• Third,Using final to Prevent Inheritance.
Using final to Prevent Overriding