Chapter6-OOP

shoulderscobblerInternet και Εφαρμογές Web

2 Φεβ 2013 (πριν από 4 χρόνια και 6 μήνες)

195 εμφανίσεις

Chapter
6.

Object Oriented Programming Languages


This chapter covers an introduction to
Object Oriented Programming
(OOP)
concepts.
Taking examples from C++, Java
,
C#,

Ruby and Python,

the concepts are elaborated
here.

The major concepts covered in this c
hapter are:

6.1.

Introduction

6.2.

Various design issues for OOPs

6.3.

C++ and its support for OOP

6.4.

Java and its support for OOP

6.5.

C#
and its support for OOP

6.6.

Ruby
and its support for OOP

6.7.

Python
and its support for OOP

6.8.

Differences between Java and C++

6.9.

Event Handling in Java

6.10.

Programming in Object Oriented Languages


Objective:

This chapter just covers the basics of object oriented programming languages.
As an introduction, this chapter covers the topics like abstraction, encapsulation, classes,
inheritance, abstract methods an
d classes, objects, static and dynamic binding. Also, this
chapter covers briefly about how languages like C++
,
Java
,
C#
, Ruby and Python

support
Object Orientation.


6.
1. Introduction:


6.
1.1. Motivation for Object Oriented Languages:

Here are few aspects

that acted as
motivation behind the development of object oriented languages from imperative
languages:



A common desire among developers was to encapsulate and reuse

programs and
data structures.

Inheritance

paved the way for reusability of various entiti
es.




The concept of reuse of certain components means the given object should be
able to be extended or restricted or partially redefined and also provide
polymorphism

and
abstraction
. By extension, we mean that the derived
entity could add more components
. Using restriction, the derivation is
restricted only towards a specific group or user. Using partially redefined,
certain components of the base entity could be changed in the derived entity
and could be reused further on.



Allowing polymorphism with gene
ric data structures. This way, different data
types could be passed to a specified method.



One notable

drawback of
imperative programming is that the global variables can
be accessed by every part of the program and it is not controlled.
Thus the concept
o
f instance variables in Object oriented languages.


6.
1.2. Object Oriented Programming Types:

Object Oriented Programming (OOP)
languages are of few categories like:

1.

Languages to which OOP was an added feature: C++ is called as
relative OOP

because the pro
grammer can write non
-
object
-
oriented programs as well. C++ and
Ada supports procedural and data
-
oriented programming. CLOS and Scheme
languages do support functional programming.

2.

Languages support OOP but the appearance and basic structure is similar to
i
mperative languages. Java is based on C++. Eiffel is not based directly on any
previous language.

3.

Pure OOP languages:
A language is called as pure OOP language provided it
supports the following:



Encapsulation and Information hiding



Inheritance



Polymorphis
m and Dynamic Binding



All pre
-
defined types in the language are objects



All user
-
defined types are also objects



Any operation required is handled by sending messages to objects

Examples of this type are

Smalltalk
, Eiffel,
and
Ruby
.


Different paradigms evo
lved as procedural (in 1950s to 1970s), data
-
oriented (in early
1980s) and Object Oriented Programming (in late 1980s).
A programming language with
OOP support produces Data Abstraction, Encapsulation, Inheritance and Polymorphism.


6.
1.
3
.
Abstraction:

Abs
traction is the process of making complex stuff simple by
providing appropriate classes to represent those complex entities.
Classes provide
abstraction of a thing (object) which contains the characteristics (attributes) and the
behaviour (methods).
Genera
l imperative programs provide pre
-
defined abstractions but
OOP supports both pre
-
defined and user
-
defined abstractions
. Usage of function

allows
the programmer to use procedural or functional abstraction where the programmer is only
concerned with the inte
rface of the function and what it computes
, i.e.,
what

of the
module is provided but not
how

of the module
.
Data Abstraction

is the encapsulation
mechanism to limit both the scope and the visibility of the data values and functions
defined for the values.
Process Abstraction

is the way to say what has to be done and not
how to do it. As an example of process abstraction, we have many
sort

methods available
in various languages

which hide the actual implementation of the sorting algorithm
.

In imperative lang
uages, even with
data abstraction, the data present are
still
independent
and are not relatively joined and are considered to be at the same level. These issues are
raised and solved in Object Oriented languages.

In OOP, data type is bound together with
th
e initializations and other operations on the specified type. This data type is referred to
as a class, local variables are called
as

instance variables
, and other operations are
implemented by methods.

If a variable is hidden from the client, then it coul
d be accessed
using accessor
(getter and setter)
methods.


6.
1.
3.1
. Abstract Data Types:

Abstract data type is the process of creating new objects
and hiding its representation from the program units that use them. Actual representation
or implementation o
f the operations is not known to the user but the possible operations
are known to the user. Data abstraction can make the process of modification and
recompilation easier because any change that ought to be made can be made without
requiring any changes t
o the clients and can be compiled separately. As a security
measure, user code cannot directly access objects. An example of built
-
in abstract data
type is
int

type in Java. The representation is hidden and the operations associated with
this type are buil
t
-
in. Data abstraction could be done to hide the functional
implementation but not the definition, to hide the constructor or destructor for the class,
etc.


6.1.3.2. Classes

and Objects
:

The most common abstract data type used in OOP are
classes
.
Class
i
nstances are called as
objects
. A class that inherits is called a
derived
class

or a
subclass
. The class from which another class inherits is called as a
parent
class

or
superclass
. A class which is within a class is called as
inner class
. Subprograms
that

define operations on objects are called as
methods
. Calls to methods are called as
messages, which are made up of a method name and destination object. Checking is done
to determine what messages are legal and precisely which method is being called. This
checking is done at compile
-
time in statically
-
typed languages like Java and checking is
done at run
-
time in dynamically checked languages like Smalltalk.
All the

methods of an
object

are
jointly

called
as

message protocol

or
message interface
.


A class ca
n be made up of two types of variables:
class variable

which is one per class
and
instance variable

which is one per object. A class can be made up of two kinds of
methods: class methods that accept messages to the class and instance methods that
accept me
ssages to objects. Class can also support single or multiple inheritances. This
inheritance creates interdependencies among classes that could complicate maintenance.


Handling of type management in Classes:

Classes could be specifically excluded from typ
e checking. In the case of Objective
-
C
language, objects would then become typeless entities, whose class membership would
be maintained separately from the type system at runtime using a tagging mechanism.


Classes could become type constructors, thus mak
ing class declarations as part of the
language type system. In C++, class is just a different form of record, or structure type. If
x

is an object of a descendant class and
y

is an object of the base class, then type
checking must permit the assignment
y =

x

but must flag the assignment
x = y

as an error.
This complicates the type
-
checking algorithm. Here is a C++ example that shows you
how type checking is done.

#include <iostream>

using namespace std;

class baseclass

{


public:


baseclass() { x = 0; cout

<< "Base class constructor" << endl;}


private:


int x; // private variable

};

class subclass: public baseclass // inheritance

{


public:


subclass() { s = 0; cout << "Subclass constructor" << endl;}


private:


int s;

};

int main()

{

baseclass e; // ca
lls the base class constructor

subclass s; // calls both base class and sub class constructors

e = (baseclass) s; // is allowed

// e = s; // is allowed and same as previous statement

// s = (subclass) e; // Compilation error
-

not allowed

}


Classes can al
so become the type system. Thus, all other structured types are excluded
from the language. In Java, class and array are the only two structured types. Using
classes as the basis for the type system means that, under static typing, the validity of all
obje
ct assignments can be checked prior to execution, even though exact class
membership is not known until execution time.


6.
1.
4
.
Encapsulation:

Encapsulation is the technique of packaging
things
together
so as
to form a

well
-
defined programming unit.
By pac
kaging things, e
ncapsulation
isolates
the
operational details of a procedure from
its usage
.
With encapsulation, the user does not
need to know the hidden information or the user is not permitted to manipulate the hidden
information. Thus, encapsulation pr
ovides both group of entities and also some data
protection.
For example, integer type hides the internal structure of integer and also does
not permit the user from manipulating the bits.

Classes help us to group things but does
not hide or separate the i
mplementation from the interface.
The
implementation
of the
methods could be hidden from the clients
while providing
the interface
,

using modules or
namespaces or packages.

Encapsulation Constructs:

To handle large programs, we could divide the program int
o
small subprograms called as
Modules

or by means of partial compilation which is of
smaller compilation units. Encapsulation is the process of grouping subprograms which
are logically related
but

are separately compiled called as
compilation units
.


Nami
ng Encapsulation:

Here, we divide large programs into many global names based
on logical groupings. A naming encapsulation is used to create a new scope of names.
Examples of naming encapsulation are
C++ Namespaces

and
Java Packages
.

Encapsulation in C:

Fi
les containing one or more subprograms can be independently
compiled. Interface is placed in a header file.

Encapsulation in C++:

This is similar to C. Friend functions that have access to private
members of the friend class, is an addition.

Encapsulation
in C#:

C# Assembly

provides the concept of combining many files into
one single executable file or a dynamic link library.

Encapsulation in Ruby:

Ruby has
modules

which are used to encapsulate methods and
constants.

Encapsulation in Ada:

Ada package

can i
nclude any number of data and subprogram
declarations, in the form of file hierarchies. Ada package is divided into two parts:
specification and body. These two parts are compiled separately. Visibility from a
program unit is gained using the
with

clause.


6.
1.
4.1.

Information Hiding
:

I
nformation hiding

means providing the interface to
reveal those that ought to be revealed. Information hiding is different from Encapsulation
in the sense that
it hides information by providing the interface
only but in encap
sulation,

it's the packaging that makes the information hidden.



Language design issues involved in creating abstract data types:

While designing an
abstract data type, we need to consider whether we want a single or a complex type, can
abstract types be

sent as parameters, and do we have access controls like
get

to read these
abstract types. Simula 67 provides encapsulation but with no information hiding. In C++,
data abstraction is based on C type
struct

and
class
es are used as an encapsulation
device.
Private clause is used for hidden entities, public clause is used for interface
entities and protected clause is used in inheritance.


6.
1.
5
.
Constructor
s and Destructors
:

Memory allocation for the object and
initialization of the instance
variables are d
one by the constructor.
Constructors are those
functions that initialize data members of instances but do not create the instances. They
are used to allocate storage and are implicitly called when the class is instantiated.
Constructors are given the same
name as the class name and can be with or without
parameters. Constructors could also be overloaded based on the parameters (
with
different signatures
)
. If no explicit constructor is provided

by the programmer
, a
parameterless constructor is supplied autom
atically

by the compiler, in certain languages
like C++.
The constructor without any parameter is cal
led as the
default constructor
.

Java constructor is with the same name as that of the class.

Destructors are used to cleanup or reclaim the heap storage on
ce the instance is
destroyed. Similar to constructor, they are also implicitly called but when the object
lifetime ends. They are with the same name as the class name but with a tilde preceded.
Destructor must be parameterless.


6.
1.
6
. Inheritance:

Inheri
tance can be complicated using access controls on encapsulated
entities. A class can hide entities from its subclasses. A class can hide entities from its
clients, which is a user of that class. A class can also hide entities from its clients while
allowin
g its subclasses to see them. Class can also modify the inherited method as: New
method can override the inherited one and the method in the parent is overridden.

Thus,
code reuse is provided using inheritance.


public class test {



public int a;

// insta
nce variables of the class.



public test( ) { … }

// constructor of the class.



// methods specified in the class.



public <type> functionname ( parameters ) { …

}


}


int main ( )

{



test y;



// This part is the client of the class
as
it uses the c
lass.


// y is an object or instance of the class.


}


6.1.6.1.

Single and Multiple Inheritance:

If a subclass inherits from only one parent class, then it uses
single inheritance
. If a
subclass inherits from more than one parent class, then it uses
multiple inhe
ritance
.
Multiple Inheritance can cause disadvantages by making complexity in language and
implementation due to name collisions. Dynamic binding do occur more with multiple
inheritance as thus causing potential inefficiency.

As an advantage, sometimes
mul
tiple
inheritance

is extremely convenient and valuable.

A
D
C
B
A
A
B
C
D

Figure 6.
1
. Multiple Inheritance

Here,
classes
B and C are derived from the common parent A. Also,
class
D has both B
and C as parents. This kind of setup is called

as
diamond

or
shared

inheritance. Issues in
having Multiple Inheritance: If
class
D derives a method from
class
A, and if this method
is redefined both by
classes
B and C, which one of them is inherited by
class
D? What
happens if

class

C has redefined th
e method but
class
B has not defined the method?


Keeping the above complexities in mind, does the programming language permit
Multiple inheritance or not. If yes, how are these complexities handled?


6.
1.
7
.
Polymorphism:

Polymorphic variable can be define
d in a class that is able to
reference or point to objects of the class and objects of any of its descendants
. When a
class hierarchy includes classes that override methods and such
overridden
methods are
called through a
polymorphic variable

(or
assignmen
t polymorphism
)
, the binding to
the correct method must be handled dynamically.
A simple example of polymorphic
variable is:
ParentClass
sampleobject

= new ChildClass();

a.

P
ure polymorphism

occurs when a single function can be applied to varied type
of argum
ents.

Here, a polymorphic variable could be pass an argument to the
function.

import java.util.*;

class ParentClass

{

void fn(){ System.out.println("ParentClass.fn"); }

}

class ChildClass extends ParentClass

{


void fn(){ System.out.println("ChildClass
.fn"); }

}

public class PurePolymorphism

{


public static void function(ParentClass x) {


System.out.println("function");


x.fn();


}


public static void main(String[] args)


{


ParentClass test = new ChildClass();


function(test);


test.
fn();

}

}

b.

Inclusion polymorphism or overriding
means that child class has the function
with the same signature as that of the parent class.

Here is a Java example for
overriding.

class baseclass{


public void multOverride(int i, int j){



int n = i*j;



Sy
stem.out.println(n);


}

}

class Overriding extends baseclass {


// same signature as base class but different implementation


public void multOverride(int i, int j){



int n = i*j*2; // multiple i and j by 2.



System.out.println(n);


}

}

public class Over
loadingOverriding{


public static void main(String[] args){



Overriding override = new Overriding();



override.multOverride(1,2);


}

}

c.

Subtype polymorphism

is where all the operations of one type can be applied to
that of another type.



In the example
of

Pure polymorphism
, the
test

object is created using
ChildClass

[
ParentClass test = new ChildClass();
] but passed as
actual parameter to the formal parameter which is a
ParentClass

object in the
method called
function
.

Thus sometimes,
Pure polymorphism

is
also called
as
Subtype polymorphism
.



As an alternative,
Inclusion polymorphism

is also called as
Subtype
polymorphism
.

Let's see a Java example of this case.

Here the creation of the
objects
test1

(of class
ChildClass1
)
and
test2

(of class
ChildClass
2
)
are

done
with the
ParentClass

as its type.

import java.util.*;

abstract class ParentClass

{


abstract void fn();

}

class ChildClass1 extends ParentClass

{


void fn(){ System.out.println("ChildClass1.fn"); }

}

class ChildClass2 extends ParentClass

{


voi
d fn(){ System.out.println("ChildClass2.fn"); }

}

public class SubtypePolymorphism

{


public static void main(String[] args)


{


ParentClass test1 = new ChildClass1();


test1.fn();


ParentClass test2 = new ChildClass2();


test2.fn();


}

}

d.

Adhoc
polymorphism

or
overloading

means there are a number of different
functions that are denoted by the same name but with different signatures. Here is
a Java example for overloading.

class Overloading {


// Methods with same name but with different signature
s


public void addOverload(int i, int j){



int n = i+j;



System.out.println(n);


}


public void addOverload(int i, int j, int k){



int n = i+j+k;



System.out.println(n);


}

}

public class OverloadingOverriding{


public static void main(String[] args){



Overloading overload = new Overloading();



overload.addOverload(1,2);




overload.addOverload(1,2,3);


}

}

e.

Parametric polymorphism

means that the type
of the
parameters are unspecified
in declarations. Examples of parametric polymorphism are ML type v
ariables,
Ada generic packages and C++ templates. Function may be applied to any
arguments whose types match a type expression involving type variables. Ada
supports parametric polymorphism with types, subscript ranges and constant
values as generic. C++ s
upports parametric polymorphism using templated
functions.

Ada Generic Packages:

This makes the stack type more flexible by making the
element type and the size of the stack generic.

package INT_STACK is new GENERIC_STACK(100, INTEGER);

package FLOAT_STAC
K is new GENERIC_STACK(500, FLOAT);


C++ Template:

C++ template functions are instantiated implicitly when the
function is named in a call or when its address is taken with the
&

operator.

#include <iostream>

using namespace std;


template <typename T>

T
max(T x, T y)

{ return x > y ? x : y; }


int main()

{

int i = 1 ,j = 2;

cout << max(i,j) << endl; // Prints 2

float a = 2.0, b = 3.0;

cout << max(a,b) << endl; // Prints 3

string s = "abc", t = "def";

cout << max(s,t) << endl; // Prints def

return 0;

}


C# uses generics, instead of templates. Comparing C++ templates with C#
generics, generics are handled at runtime while templates are handled at compile
time.


6.1.7.1.
Type checking and polymorphism:
Polymorphism may require dynamic type
checking of para
meters and the return value. Dynamic type checking is costly and delays
error detection. If overriding methods are restricted to have the same parameter types and
return type, then checking can be static.

Type checking ought to be done between the
actual a
nd formal parameters and between the return type and the expected return type.
Certain languages allow
different
type compatibilities
while performing type checking in
parameters and return type
elements
.


6.
1.
8
.
Abstract Method and Class:

An abstract meth
od is one that does not include
the
implementation of the method
but has
the protocol (definition). An
abstract class is one
that includes at least one abstract method. An abstract class cannot be instantiated and are
used to define a public interface to b
e shared by a set of classes. Abstract classes differ
from concrete classes in
the sense
that instance variables are often declared to be
protected
(can be accessed by subclasses)
instead of private

(cannot be accessed by
subclass)
, so that the subclasses
can reference them. Abstract methods are sometimes
called
deferred

and a class that has a deferred method is called a
deferred class
. It is
called so because the implementation is deferred until a subclass defines it.

Instance
variables present in the abst
ract class should not be specified as private because otherwise
it won't be accessible by subclasses.


Method categories:

Methods are of three categories:
Unary
,
Binary

and
Keyword

messages. Unary messages have no parameters but include the object to which

they are to
be sent and the name of the method in that receiving object. Binary messages have a
single parameter which is an object which is passed to the specified method of the
specified receiver object. Keyword messages are those
where
one or more keyw
ords are
specified to be in correspondence between actual parameters in the message and the
formal parameters in the method.


Various Class types:

1.

Data Manager Classes:

The data managed is either
called as
data

or
state
.
Data
Manager
Classes

maintain data
or state information.

2.

Data Sinks or Data Sources Classes:

Generates data like a random number
generator but does not hold the data for any period of time.

3.

View or Observer Classes:

Displays the information on an output device such as a
terminal screen.

4.

Fac
ilitator or Helper Classes:

Used to do complex tasks but ha
s very minimal or
no

state information

themselves
.


6.1.
9
. Exceptions:

An Exception is any unexpected or infrequent event which is raised
and thrown, during runtime. An execution handler is a proc
edure or code sequence that is
designed to be executed when a particular exception is raised and that is supposed to
make it possible for normal exception in some way. An exception handler is said to
handle or catch an exception. Exception handler might ca
use the program to be continued
(called as
resumption model
) or terminated (called as
termination model
). In the
resumption model, the process of returning back through function calls to the caller
during the search for a handler is called
call unwinding

o
r
stack unwinding
. Generally,
all programming languages support termination model of exception handling. This might
be because that it is easier to implement termination model than resumption model.
Exception handling is not available in C language.


Synch
ronous exception is caused by errors that the programs can definitely catch.
Asynchronous exception is something that could happen any time and might be due to
failure of hardware devices or memory allocation or communication problems. While
analyzing any
language, exceptions related conditions that ought to be checked are:

1.

Presence or absence of predefined exceptions in the language. Also, can we
disable predefined exceptions or not.

2.

Scope of user
-
defined exceptions.

3.

Scope of exception handlers. Whether th
ere is default handler for any specific
predefined exception, ought to be checked.

4.

Passing of control to the handler. After the completion of the execution of the
handler, does the process continue or terminate.


6.1.10. Object and Class representations:

In the area of software engineering, classes,
objects and their attributes/relationships are represented in the form of certain diagrams:
class diagram, object diagram. Class diagram is used to provide information about the
class; object diagram is used to

indicate information about objects.

These representations
are done using Unified Modeling Language (UML).

6.1.10.1. General representations in Class/Object diagram:

Classes/Objects are
represented using boxes and links are used to indicate relationships.

The class
diagram is of three rows, representing the class name, attributes

(member
variables)

and the operations

(member functions)

associated with the class.

6.1.10.2. Visibility in Class diagram:

Visibility of various members (methods and
attributes) of

any class is represented using
+

(public) or
#

(protected) or


(private) or
~

(package).



class classname

{


public:


int varInt;

function
()


{ varInt = 0; }

};



6.1.10.3.
Association in Class diagram:

Association indicates a "owns a"
relationship.

Association is represented by one or more links or lines. This
indicates actions of one class on another. As an example,
company offers
trainings
.

Company and Tr
aining are classes. O
ne company (1) can
conduct

many (1..*) trainings.

Company
Training
1
1
..*

6.1.10.4. Aggregation and Composition:

Aggregation indicates a "has a"
relation
ship while composition is a stricter version of

"owns a" relationship.
Aggregation occurs when a class is a collection or a container of other classes. In
aggregation, if

the container

(Toyoto)

is destroyed, the contents
(Car)
are not
destroyed. But in composition, if the container
(Circle)
is destroyed, the contents

(Point)

are also destroyed.

Aggregation



Composition


6.1.10.5. Generalization:

Generalization is used t
o indicate the "is a" inheritance
concept. The subclasses are considered to be a specialized form of the superclass.

SubClass
1
BaseClass
SubClass
2

If instead of inheriting an implementation, we inherit an interface, then the
notation is changed as:

SubClass
1
Interface
SubClass
2

6.1.10.6. Dependency:

Dependency is used to indicate a weak relationship
between two or more classes. This dependency might exist at some point of time.

Here, any change made on
Package 2

will affect
Package 1
.

As an example, to
draw

a Shape, we need a DrawingContext
class
.

Package
1
Package
2

6.1.11.
Object data representation
:

Class instance record (CIR) is used along with
virtual method table (
or virtual function table or dispatch table or
vtable) to represen
t a
class in
the memory. CIR
contains the necessary member variables and a pointer to the
vtable
(called as vpointer or virtual table pointer)
that contains the member functions

that
ought to be dynamically bound
.

S
a
mple C++ program:

class A

{


public:


void fn1() {
}

virtual void fn2() {}

int avar;

};

class B : public A

{


public:


void fn2() {}


int bvar;

};

int main()

{



B *b1 = new B();

}

Memory layout for object b1

Pointer to vtable of
class A
int avar
int bvar
A
::
fn
2
vtable of class A


vtable contains only the member variables
and pointer
s

to
other vt
ables
.

The non
-
virtual functions are not stored in the
vtable.

Sample
Java

program:

class A

{


public

int avar;


public void fn1() { }


public
void fn
2
() { }

};

c
lass B

extends

A

{


public

void fn2() {}

public

int bvar;

};

public Sample

{


public
static
v
oid
main(
S
tring[] args
)


{



B b1 = new B();


}

}

Memory layout for object b1


Pointer to vtable of
class B
int avar
int bvar
vtable of class B
CIR of class B
A’s fn
1
B’s fn
2


In Java, all methods are dynamically
bounded and thus all methods exist in the
vtable.


6.
2
.
Various
other
design issues
in
OOP:

6.2.1.

Exclusive natu
re of Objects
:

In order to make any language as totally object
oriented language, e
verything
(even the primitive data types like integer)
is considered as
an object.
This
provides elegance and purity for the programming but slows the
operations on simple o
bjects.

Two alternative approaches exist:

a.

As an alternative, an object oriented language can be generated just by adding
objects to a complete

imperative

typing system.
By doing this, w
e could make fast
operations on simple objects but might result in a

co
nfusing type system with two
kinds of entities
.

b.

Yet another alternative way would be to i
nclude an imperative style typing system
for primitive

data types

with
everything else as objects. This system can cause fast
operations on simple objects and a relat
ively small typing system. This might
cause some confusion
among programmers due to
the
presence of
two type
systems.


6.2.2.

Subclasses as subtypes:

The
"
is
-
a
"

relationship

holds between a parent class
object and an object of the subclass.

The
"
is
-
a
"

relationshi
p guarantees that a variable of
the derived class type could appear anywhere a variable of the parent class type
is

legal,
without causing a type error.

In certain cases, a subclass might vary from the base class
by including
new methods

or
metho
ds with di
fferent signature
.

If there exists a "is
-
a"
relationship between the parent and the subclass, then the subclass is called as
subtype
.

Being a subtype restricts the subclass to have methods with the same signature as that of
the parent class.

Base Class
Shape
Sub Class
Circle
Is
-
A Link

Figure
6.
2
. Is
-
A Relationship


6.2.3.

Allocation and De
-
allocation of objects:

Allocation and de
-
allo
cation of objects
can be done on

heap or run
-
time stack. If objects live in heap, then references to them
could be handled uniformly.

a.

If object a
llocation is done in stack, then there is a limitation on the expandability
of the element.
Let’s consider an example where
p1

is a variable of the parent
class and
c1

is a variable of the subclass. After creating space for
p1

on the stack,
if the assignme
nt statement
p1 = c1

is introduced there is a problem of memory
allocation if the subclass has extra new data fields compared to that of the parent
class.

b.

If object allocation is done o
n heap,
i
s
de
-
allocation

done implicitly or explicitly?
Care must be t
aken to handle dangling pointers and to meet effective garbage
collection requirements.


6.2.4.

Implementation and interface inheritance:

a.

If only the interface of the parent class is visible to the subclass, it is
called as
interface inheritance
. This can result

in inefficiencies.

b.

If the subclass inherits the exact behaviour of the parent by default,
it is

called as

implementation inheritance
.
Subclass can also explicitly override the behaviour
of the parent class.
The implementation present in the parent class r
emains
hidden, irrespective of whether the parent's behaviour is overridden by the
subclass or not.
Changes made to the parent class require recompilation of
subclasses, and sometimes even modification of subclasses.


6.2.5.

D
ynamic (Late binding) and static bind
ing:

Keeping all binding of messages
to
methods as dynamic will make the process slower
and thus inefficient.
At the same time,
with

dynamic binding, you could easily create and destroy objects whenever needed, thus
efficiently using the available memory.

Dynamic binding should be handled at runtime
because dynamic method calls can not be resolved at compile time.


6.2.6.

Copying of assignment values:

During an assignment statement, expression on
the right hand side is evaluated and the result is copied from the r
ight hand side to the left
hand side of the assignment statement. Two different semantics exist when copying
assignment values:
copy semantics

and
reference semantics
. Copy semantics (also called
as
value semantics
) means the value of the particular elemen
t is copied and not the
pointer. Reference semantics (also called as
pointer
-
copy semantics
) means that the
pointer is

copied and not the values.
Java like Smalltalk uses reference semantics for
arrays and objects. But for primitive data types, Java uses c
opy semantics.

C
and C++ languages support reference semantics for arrays.
C++
supports both
copy
and reference
semantics for
objects.

In the following C example,
assigning the array
variables to one another
results in compilation error.

#include <stdio.h
>

int main()

{

int array1[3] = {1,2,3};

int array
2
[3] = {2,3,4};

array
1

= array
2
;
//
compilation error.

return 0;

}

The following C++ example indicates how to implement copy as well as reference
semantics on C++ objects.

#include <iostream>

using namesp
ace std;

class A

{

public:


int i;



A() { i=0; }



A(int j) { i=j; }

};



int main()

{


A *rs1 = new A(10);


A *rs2;




// reference semantics


rs2=rs1;


cout<<"Address of RS1:"<<rs1 << endl;


cout<<"Address of RS2:"<<rs2

<< endl;


cout<<"Value at RS1:"<<rs1
-
>i << endl;


cout<<"Value at RS2:"<<rs2
-
>i << endl;




delete rs2;


cout<<"Address of RS1 after
delete:"<<rs1 << endl;


cout<<"Address of RS2 after
delete:"<<rs2 << endl;


cout<<"Value in RS1 after
delete:"<<rs1
-
>i <<
endl;


cout<<"Value in RS2 after
delete:"<<rs2
-
>i << endl;



Output:

// reference semantics

Address of RS1:0x10a2dc8

Address of RS2:0x10a2dc8

Value at RS1:10

Value at RS2:10


// Both RS1 and RS2 remains th
e same
address. Referring to the same location
indicates the same value.


Address of RS1 after delete:0x10a2dc8

Address of RS2 after delete:0x10a2dc8

Value in RS1 after delete:1628741076

Value in RS2 after delete:1628741076


// Once one of them is deleted
the value is
lost for both as they both referred to the same
location.


// copy semantics

// Different address locations but the value
remains the same.


Address of CS1:0x22cc98

Address of CS2:0x22cc94

Value in CS1:10

Value in CS2:10


A cs1(10);


A cs2;




//copy semantics


cs2 = cs1;


// Contents remain the same


// Address remains different


cout<<"Address of CS1:"<<&cs1 << endl;


cout<<"Address o
f CS2:"<<&cs2 << endl;


cout<<"Value in CS1:"<<cs1.i << endl;


cout<<"Value in CS2:"<<cs2.i<<endl;


return 0;

}


In reference semanti
cs, the assignment
a = b

forces
a

and
b

to refer to the same object
and thus any change to
a

changes
b

and vice versa. To derive the effect of copy semantics
in Java, you must use an object
'
s
clone( )

method.

Let's
consider a Java
example where an
array is

manipulated with and without
clone( )

method.

class
Example

{ public static void main(String[] args)


{ int[] x = {1,2,3};


int[] y = x;


x[0] = 4
0
;


System.out.println("y[0] = " + y[0]); // Prints 4
0


System.out.println("x[1] = " + x[1]); // Prin
ts 2


System.out.println("y[1] = " + y[1]); // Prints 2


int[] y1 = (int[])x. clone();


System.out.println("y1[0] = " + y1[0]); // Prints 4
0


System.out.println("x[0] = " + x[0]); // Prints 4
0


y1[1] = 10;

// this change impacts only y1 and not x

or y


System.out.println("y[1]= " + y[1]); // Prints 2


System.out.println("x[1]= " + x[1]); // Prints 2


System.out.println("y1[1] = " + y1[1]); // Prints 10


}

}


Example
6.
2: Discuss reasons for opting for dynamic binding over static binding?

Dy
namic binding provides flexibility in the sense that not all design decisions need to
be made during the initial stage of the system development. For example, if generic
methods are used they could be mapped during runtime. Binding the type of a
variable o
r an object could be done at run time.

Static binding does not have the same overhead of the dynamic binding and so should
be used if it is known in advance that the method will not be overridden with new
types or there is no need for dynamic binding.


6.
3
.
C++ and its support for OOP:

Main function returns a value back to the operating
system which is used by operating system to determine whether the program ended
correctly or not. Any function that returns nothing is given a return type of
void
. Main
func
tion returns an integer but we indicate the return type as void to indicate no return
value. Header files can be used to place class declarations in different files. Destructor
procedure

(represented by the same class name preceded by a tilde)

is called
au
tomatically just before the object disappears.
Instance variables and methods are called
as members of a class; while specifically, instance variables are called as
data members

and methods are called as
member functions
. Subclasses are called as
derived c
lasses

and superclasses are called as
base classes
.

C++ uses mixed type system because it
includes the type system of C and adds classes to it. C++ supports both object oriented
and imperative type of coding and thus uses static binding by default. If dyna
mic binding
has to be enabled for a specific method, then the keyword
virtual

has to be used. In C++,
objects are created on stack

as well as on heap
.
Java or Simula or Smalltalk use heap for
creating objects.

As indicated in the
Imperative Languages c
hapt
er, C# uses both stack
and heap depending upon what and how things are stored.


Static/Dynamic Memory Allocation in C++:

In order to dynamically allocate an object,
we use the keyword
new

followed by the name of the class from which the object is to be
cre
ated and a parameter list that matches one of these constructors. The
new

operator is
used to allocate memory for an object, take the input parameters and passes them into the
object constructor, and returns a pointer to the memory location of the created
object.


Creating an object on the stack is short lived as the object will be deleted from the stack
moment the control leaves the innermost compound statement that contains the object
creation statement.

Creating objects on the stack:

classname classnam
e(arguments);

Creating objects on the heap:

classname* objectname = new classname(arguments);

delete objectname;

// delete the object


Creating objects in C++ could be done by providing a global or local variable for a class.
When the variable is declared
, the space required for the object is allocated and
constructor is called. Objects can also be created using
new

operator, which also creates
space and calls the constructor.

class baseclass

{


public:


baseclass(void) { cout << "Base class constructor"

<< endl;}

};

int main(void)

{

baseclass e;

// creates an object and calls the base class constructor

}


If an object of a subclass that has extra attributes is copied onto an object of the super
class, then only those attributes defined in super class ar
e copied. This process of not
copying everything is called as
slicing
.


Accessing members of Class:

When the object is statically allocated, dot operator "
.
"

is
used as the member access operator
. When the object is dynamically allocated, arrow
operator
"
-
>
"

is used as the member access operator
. The pointer to an object that
precede the
-
> and the name of the function identifies the class from which the correct
function should be taken.


Example
6.
3:

(a)

Show various examples to indicate objects creation
(
and accessing
methods)
on stack and heap in
C++?

ClassName ObjectName
1
;


// Creating an object on the stack

ClassName *ObjectName
2
;

// No object is created

// Creating an object on the heap

ClassName *ObjectName3 = new ClassName(arguments);

// ObjectName1
and ObjectName2 are the same object

// ObjectName1 is the actual object; ObjectName2 is just the reference

ObjectName2 = &ObjectName1;

// Accessing methods

ObjectName1.MethodName();

ObjectName2
-
>MethodName();

ObjectName3
-
>MethodName();

// Creating an objec
t on the heap

// ObjectName1 and ObjectName2 are different objects

ObjectName2 = new ClassName(arguments);

// Object creation by copying

// ObjectName1 and ObjectName2 are different but identical objects

ObjectName1 = *ObjectName2;


Example
6.
3:

(
b
)

What
is the use of virtual pointer in C++?

Virtual pointer is possessed by every polymorphic class. The use of this pointer is to
contain the address of a dispatch table that contains the addresses of all the virtual
member functions for the specific class.


Ex
ample
6.
3:
(
c
) Show with a simple
C++

program
,

the invocation

o
f

constructor and
destructor

methods
.

#include <iostream>

using namespace std;


class RectangleClass {


int width, height;


public:


RectangleClass (int a,int b)


{ width = a; heigh
t = b;};


~RectangleClass ()


{ cout << "inside destructor" <<
endl;};


int area ()


{ return (width * height);}

};


int main () {

RectangleClass rectanglea(3,4);

RectangleClass rectangleb(
1
,
2
);


cout << "rectangle A's area: " <<
rectangl
ea.area() << endl;


cout << "rectangle B's area: " <<
rectangleb.area() << endl;


return 0;

}

Output:

Rectangle A's area: 12

Rectangle B's area:
2

inside destructor

inside destructor


The destructor is twice called
because two objects were
created.


6.
3
.1.
Inheritance

in C++
:

A class need not be a subclass for any other class. Access
controls for members can be
private

or
public

or
protected
. Private members are visible
only to the class and the friends. Public members are visible in subclasses and clien
ts.
Protected members are visible in the class and in the subclasses but not in the clients.
Subclassing can be done using access controls like private or public. Private derivation
means inherited public and protected members are private in the subclasses
.

Public
derivation means public and protected members are also public and protected in
subclasses.

C++ uses
public

derivation by default if the derived class is declared with
struct

keyword and uses
private

derivation by default if the derived class is de
clared
with
class

keyword.

class A {};

class B : A

// private derivation

{ };

struct A { };

class B: A

// private derivation

{ };

class A {};

struct B :
A

// public derivation

{ };


Inheritance is said to be of implementation inheritance and interface/
subtype inheritance.
Implementation inheritance means that the subclass inherits part or all of its
implementation from the parent class.


Example
6.
3.1:
(a)
Write about type conversions between base and derived classes in
C++.

Up
-
conversion or narrowing:
Assigning of derived class to a parent class is implicitly
allowed in C++. Conversion is done upwards from a descendant (derived class) to
any of its ancestors (parent class). Here, the derived class should have extra field and
so it is widened and when we

convert to parent class, we are narrowing the
information.

Down
-
conversion or widening: This is not allowed as it is not clear what to do with
the extra fields present in the derived class. We are widening the information as there
are extra fields in the
derived class. dynamic_cast is present in C++ to help convert
certain widening cases.

#include <iostream>

using namespace std;

class A {


public: virtual void func() {

cout << "Function func in Class A" << endl; }

};

class B : public A {


public: virtua
l void func() {

cout << "Function func in Class B" << endl; }

};

void func1(A* arg) {


B* bp = dynamic_cast<B*>(arg);


bp
-
>func();

};

int main() {


A aobj;


B bobj;


A* ap = &bobj;


ap
-
>func(); // Prints Class B


func1(ap); // Prints Class B

}


Exa
mple
6.
3.1:
(b) Explain virtual class (virtual inheritance, diamond inheritance) in
C++ with
appropriate
examples
.

#include <iostream>

using namespace std;


class A {

public:


virtual void printvirtual()


{ cout << "Class A" << endl; };

};


class B : publi
c A {

public:


void printvirtual()


{ cout << "Class B" << endl; };

};


class C : public A {

public:


void printvirtual()


{ cout << "Class C" << endl; };

};


class D: public B, public C {

public:


void printvirtual()


{ cout << "Class D" << endl; };

}
;


int main()

{


D test1;

test1.printvirtual();

// prints Class D



#include <iostream>

using namespace std;


class A {

public:


virtual void printvirtual()


{
cout << "Class A" << endl; };

};


class B : public A {

public:


void printvirtual()


{ cout << "Class B" << endl; };

};


class C : public A {

public:


void printvirtual()


{ cout << "Class C" << endl; };

};


class D: public B, public C


{ };


int main()

{


D test1;

test1.printvirtual();

// error

// printvirtual is ambiguous

}

// error
-

A is an ambiguous base of D

// A test2 = (A) D();


//test2.printvirtual();




A test3 = (A) (B) D();

test3.printvirtual();

// prints Class A




B test4 = (B) D();

test4.
printvirtual();

// prints Class B




C test5 = (C) D();

test5.printvirtual();

// prints Class C




C test6 = D();

test6.printvirtual();

// prints Class C




}

#include <iostream>

using namespace std;


class A {

public:


virtual void printvirtual()


{ cout << "Class A" << endl; };

};


class B : public virtual A {

public:


void printvirt
ual()


{ cout << "Class B" << endl; };

};


class C : public virtual A {

public:


void printvirtual()


{ cout << "Class C" << endl; };

};


class D: public B, public C {

public:


void printvirtual()


{ cout << "Class D" << endl; };

};


int main()

{


D t
est1;

test1.printvirtual();

// prints Class D



A test2 = (A) D();


test2.printvirtual();

// prints Class A

#include <iostream>

using namespace std;


class A {

public:


virtual void printvirtual()


{ cout << "Class A" << endl; };

};


class B : pub
lic virtual A {

public:


void printvirtual()


{ cout << "Class B" << endl; };

};


class C : public virtual A {

public:


void printvirtual()


{ cout << "Class C" << endl; };

};


class D: public B, public C


{ };


int main()

{


D test1;

test1.printvirtua
l();

// error

// printvirtual method is not
overridden

// printvirtual is ambiguous

}



A test3 = (A) (B) D();

test3.printvirtual();

// prints Class A




B test4 = (B) D();

test4.printvirtual();

// prints Class B




C test5 =

(C) D();

test5.printvirtual();

// prints Class C




C test6 = D();

test6.printvirtual();

// prints Class C




}


6.
3
.2.
Subtyping

in C++
:

Subtype inheritance is also called as
interface inheritance
.
Here, the subclass is considered to be a subtype of its super class, referred to a
s an Is
-
A
relationship. By indicating the subclass as a subtype, it means that its object confirms to
its class or to any of its super classes.
If X inherits from Y, then C++ type checker will
allow X objects to be assigned to Y class pointers.

An example
of this subtyping is found
in Section
6.
1.
3
.


Example
6.
3.
2
: Can we consider a C++ subclass as a subtype? Explain.

A subclass is a class that is formed using inheritance from the base class. A subtype is
a class that can be substituted with no observable e
ffect, using polymorphism. Thus,
an instance of a subtype could be used instead of an instance of a supertype. Thus,
not all subclasses are subtypes. In C++, a subtype can be formed only using subclass.
In Java, subtypes can be formed using subclasses or u
sing interfaces.


6.
3
.3.
Support for Multiple Inheritance is present in C++:

If there are two inherited
members with the same name, they can both be referenced using the scope resolution
operator.


Name Clashes:

Name clash is possible if classes
A

and
B

h
ave the same name and Class
C

inherits from these two classes. To handle this clash, we could use any of the following
methods:

1.

Implicit resolution:

The language resolves
the existing
name conflict with an
arbitrary rule.

2.

Explicit resolution:

The programme
r must explicitly
specify how to resolve the
name
conflict in
his
code.

3.

Disallow name clashes:

Name clashes are not allowed in p
rograms.

C++ allows names clashes and requires explicit resolution in the program
, like the use of
scope resolution operator
.


E
xample
6.
3.3:
(a)
What does repeated inheritance means in C++?

Multiple inheritance in which there is a common grandparent is called as
repeated
inheritance
. Repeated inheritance with separate copies of the grandparents is called
as replicated inheritance.

Repeated inheritance with a single copy of the grandparent
is called as shared inheritance. C++ provides the concept of repeated inheritance in
the case of multiple inheritance, but at the same time, it expects the programmer to
specify the parent class f
rom which the feature is inherited. Thus, some would say
that C++ does not support repeated inheritance itself.


Example
6.
3.3: (b) Show with an example how conflicts in calling methods with
multiple inheritance is handled in C++.

#include <iostream>

using

namespace std;

class A {


public: virtual void test() { cout << "test in A" << endl; };

};

class B {


public: virtual void test() { cout << "test in B" << endl; };

};

class C : public A, public B

{ public:


void func() {


B::test(); // Calls the B
one


// test(); // compile error
-

it is ambiguous to call A or B


cout << "test" << endl;};

};

int main()

{


C* p = new C();


p
-
>func(); // which one is called.


return 0;

}


6.
3
.4.
Dynamic binding

in C++
:

Polymorphic variables can be accessed usin
g pointers
or references. A method can be defined to be
virtual
, which means that they can be
called through polymorphic variables and dynamically bound to messages.
Polymorphism is implemented using virtual functions. Virtual functions depend on
dynamic b
inding, since the compiler cannot always determine which version of the
function is being called. To declare a function virtual, precede its prototype with the
keyword
virtual
.
Any class with an abstract method is called as an
abstract class
, but
those whi
ch have only pure virtual methods and no data are called as
pure abstract
class
.


If there exists a derived class which has overridden certain methods in the base class and
the derived class object has been cast
ed

as the base class type, then when the over
ridden
method is called, the processing of the overridden class becomes ambiguous. This
ambiguity lies in the fact whether to call the base class function or the derived class
function. If the base class function is indicated with the keyword
virtual
, the
derived
class function is called. Otherwise, the base class function is called.


A pure virtual function is one without any definition. A class that has at least one pure
virtual function is an abstract class.

The use of abstract class is to define a clas
s as a
common interface for more than one derived classes which are not abstract.

class abc {

public:


virtual double xyz () = 0; // pure virtual



};


The zero noted in the virtual method indicates t
hat the method has no implementation

at
this point of

time. This means that this method is an abstract and can not be called or
invoked. This method will be overridden by a method definition in the derived class.


In C++, the programmer must decide at design time which methods will be statically
bound and w
hich must be dynamically bound. Static binding is handled faster.


Example
6.
3.4: It is known that instances cannot be created for an abstract class. Is it
possible to declare a pointer to abstract class in C++? Answer with an example.

#include <iostream>

using namespace std;

class test { public: virtual void func (void) = 0; };

class sub: public test {


public: void func (void) { cout << "sub"; } };

int main () {


sub test1;


test * base = &test1;


base
-
>func(); // Prints sub


return 0;

}


6.
3
.5.
Frie
nd classes and functions

in C++
:

Friend mechanism allows the programmer
to bypass class restrictions.

class A
1

{ friend class
A2
; };

Class
A
1

declares class
A2

as

its

friend.
By doing this,
member functions of class
A2

are
permitted
to directly read or mo
dify the private data
entities
of class
A
1
. A friend
function of a class is declared outside that class scope and has the right to access right
private members of the class. To declare a function as a friend of a class, precede the
function prototype in th
e class definition with the keyword
friend
.
Sometimes, friend is
used to patch problems in the project instead of rethinking the whole process of
abstraction
. In the example below, the
friendclass

is able to access the private variable
(
private_data
) prese
nt in the
mainclass
. This is because
mainclass

considers the
friendclass

as its friend.

#include <iostream>

using namespace std;

class mainclass

{


int private_data;


friend class friendclass; // friendclass is a friend


public: // does not matter if it

is private also


mainclass()


{ private_data = 10; }

};

class friendclass

{


public:


int addition(int a)


{


mainclass mainclassobj;

// access private variable of the mainclass


return mainclassobj.private_data + a;


}

};

int main()

{



friendclass friendclassobj;


cout << "Result: "<< friendclassobj.addition(5)<< endl;

}


6.
3
.
6
. Encapsulation

in C++
:

C++ Namespaces can place each library in its own
namespaces and could be accessed from outside using the qualified name
. Let's consider
a
n example in which some variables are declared with a namespace and accessed using

the keyword

using
.

#include <iostream>

using namespace std;

namespace one

{ int a = 10;}

namespace
two

{ double a = 10.1234;}

int main () {


using namespace one;


cout <<
a << endl; // access a in
one


cout << two::a << endl;

// access a in
two


using one::a;


cout << a << endl; // access a in
one


// scope for using a namespace with brackets


{ using namespace one; cout << a << endl; }


{ using namespace two; cout <<

a << endl; }


return 0;

}


6.
3
.
7
.
Templates

in C++
:

C++ Templates are used to provide overload
ed

functions. With
the help of overloaded functions, we could have a single function which could act on
integer as well as floating point numbers. Instead of wr
iting separate methods to handle
each data type, we could write a single function that could accept different data types
with the help of templates.

Let's consider a simple C++ example:

#include <iostream> // iostream.h is depreciated

using namespace std
; // needed for cout to work


template <typename T>

T min1(T x, T y) // min is an inbuilt name and thus use min1

{ return x < y ? x : y; }


int main()

{

// Here the min1 function is being called with different data
types

int i = 1 ,j = 2; cout << min1(i,j)

<< endl;

float a = 2.0, b = 3.0; cout << min1(a,b) << endl;

string s = "abc", t = "def";
cout << min1(s,t) << endl;

return 0;

}


6.3.8. Exceptions in C++:

C++ does not have predefined exception types. But, there are
standard library modules which provide
exceptions and exception mechanisms in C++.
try

and
catch

is present in C++. Examples of standard exceptions include:


bad_alloc: call to new failed.


out_of_range: subscript operations check failure.

Let's see how exceptions are handled in C++ with an exa
mple. In this example, vector is
used instead of arrays. Vectors are dynamic arrays in which memory management is
handled properly. From the example, it is obvious that out of range error is not caught in
array but caught in the case of vectors.

#include <
iostream>

#include <vector>

#include <exception>

#include <stdexcept> // out_of_range exception

using namespace std;


int main( ) {


char array[] = {'a', 'b', 'c', 'd'};


// no error is caught and just a random value is printed.


try {


cout << arra
y[10000];


} catch(std::out_of_range& e) {cerr << e.what( ) << '
\
n';}


vector<char> v;


v.push_back('a');


v.push_back('b');


v.push_back('c');


// Runtime error: vector :: _M_range_check occurs


try {


cout << v.at(10000) << '
\
n';


} catch(std:
:out_of_range& e) { cerr << e.what( ) << '
\
n';}

}

Example 6.3
.8
: (a) What is the use of throw in C++? What happens to an exception
which is not mentioned in throw? What about default? What about having
an
empty
throw?

With throw, C++ functions can specify
the possible exceptions it can raise. In the
following example, the exception is caught and both the integer and the default catch
clause are executed. If the
throw(int)

statement is removed, then the program will
work the same. But, if the
throw(int)

is c
hanged to
throw( )
, then runtime error is
generated. If there is more than one exception, only the first exception is caught and
the remaining is not handled as exception causes the program to terminate.

#include <iostream> // iostream.h is depreciated

us
ing namespace std; // needed for cout to work

void test() throw (int) {


throw 10;


cout << "After throw" << endl; // Not printed.


// this is not caught
because
only the first occurrence is
caught


throw 5;

}

int main()

{

try {test();}

catch (int

&i) { cout << "integer caught " << i << endl; }

catch (...) {cout << "Default exception" << endl;}

}


Example
6.3.8
: (
b
) Write a C++ program to catch a user
-
defined exception?

We need to inherit the exception class and then define our own exception.

#in
clude <iostream>

#include <exception>

using namespace std;

class myexception: public exception

{


char* what() const throw()


{ return "Our Testing Exception"; }

} myexcep;

int main () {


try


{ throw myexcep; }


catch (exception& e)


{ cout << e.wh
at() << endl;}


return 0;

}


Example
6.3.8
: (
c
)
Write the steps required to disable exceptions in C++ compiler.

While compiling the C++ program, the following has to be used:


g++
-
fno
-
exceptions filename.cpp


6.
4
.
Java and its support for OOP:

Java
'
s sup
port to OOP has high resemblance to that
of C++ and thus we cover only those main differences between them.



General Characteristics:

All data are objects except the primitive types. All primitive
types hav
e
wrapper classes that

store one data value (
wrap
per

Integer

for the primitive
type

int
).
Wrapper classes
are used to wrap primitive values and make them as objects.
For example, to store primitive elements like int in Vector, the values should be in object
form and not in primitive form. Thus, we need w
rapper class.

As all methods in wrapper
class are static, we could use them without creating an instance. Once a value is assigned
to a wrapper, it cannot be changed.

import java.util.*;

public class Wrapper{


public static void main(String argv[]){



Vector v = new Vector();


// add needs the parameter to be an object


// wrapper class converts the integer into an object


v.add(new Integer(10
0
));



v.add(new Integer(20
0
));



for(int i

=

0; i < v.size();

i++){


Integer i
val

=(Integ
er) v.get(i);


System.out.println(
ival
);


}

}


All objects are
allocated as
heap
-
dynamic

and

referenced through reference variables
.
M
ost
ly, objects

a
re a
llocated with
new
.
In Sun's Java, garbage collector runs as a thread
(low priority proce
ss). Being run as a thread, it runs whenever
there is not much
processing
needed by other threads. This way the need for running garbage collection at
peak times is highly reduced. Explicit calling of garbage collector in Java could be done
using
System.gc
()
. By explicitly calling the garbage collector, the garbage collector

is

initiated immediately irrespective of the current state of the heap memory.

Invoking or
automatic running of garbage collector calls a special method called
finalize

in Java,
which a
cts like a destructor.


The keyword
super
:

The keyword
super

can be used to invoke the overridden method.
The
super

keyword
makes use of the lookup table of the superclass to resolve the call.
This resolving cannot be done statically during compile time bu
t could be resolved during
load time.

class A

{ void fn
(){ System.out.println("a.
fn
"); }

}

class B extends A

{

void fn(){ System.out.println("b.fn"); super.fn
();}

}

public class Binding

{


public static void main(String[] args)


{
B

a = new
B
();


a.
fn
()
;
//
prints

b.fn

and
a.fn


}

}


Access Modifiers:

Java provides four modifiers that are frequently used to control access
to data, methods, and classes:
Static

[shared by all instances of the class],
Public
,
Protected

and
Private
. The keyword
super
is used

to refer to the superclass of the class:
super( ).


Substring method usage:

The substring method provided by Java is of the form
st
ring_
name.substring(begin,end)



Here, the

substring
method is applied on the string named

"
string_name
"
. The
substring metho
d returns all the characters from

the location
"
begin
"

till the
location just before the "end" argument, i.e., it does not include the
"
end
"

argument.
All

built
-
in String processing methods
that include substring are
consistent on how
the range is specifie
d.



Programmers

can extend the String class
by
adding their own methods
needed
to
process strings
, at any time
. This is an advantage of Object
-
oriented language
because it makes the class extensible.


6.
4
.1.
Static

field in Java
:

If a field is declared as s
tatic, then it is one per whole class
instead of an object. Static methods are meant for the class and not part of an object and
thus could be called before an object is created. Static methods could refer to static
methods and static field
s

only and the r
eference
this

is not allowed in static methods
because there is no object present.


static { … } // This is called as static initialization block.

Things specified within a static initialization block are considered to be static.

The
following Java example

prints 99 twice.

public class StaticTest

{ static int foo = 123;


static { foo = 99; System.out.println(foo);}



public static void main(String argv[]){




System.out.println(foo);



}

}


6.
4
.
2
.
Inheritance

in Java
:

A class definition uses
ext
ends

keyword to indicate its
superclass. Only single inheritance is supported in Java but there is an abstract class
category that provides some of the benefits of multiple inheritance (
interface
). An
interface declares a collection of features identified
by abstract methods. An interface is
always abstract whether it is declared abstract or not. All of the methods in an interface
must be abstract; only constant (
final

variables
)
may be concretely declared in an
interface. Because interface is a not a class
, it does not have a constructor. An interface
can include only method declarations and named constants.

A class

that

implements

an
interface
is
not extending
the interface
. When a class is implemented, then all the
methods present in the interface should
be implemented.
java.lang.System is a final class
and so its system methods can not be overwritten.

For example, the class Clock extends
the superclass Applet and implements the interface Runnable.

public class Clock extends Applet implements Runnable


Me
thods that are declared as
final

cannot be overridden. Classes that are declared as
final

cannot be the parent of any subclass.

class A

{

final void fn(){ System.out.println("a.fn"); }


}

class B extends A

{


// Compilation error


B cannot overri
de fn() in A


void fn(){ System.out.println("b.fn"); }

}

final
class
C
{ }

// Compilation error


cannot inherit from final C

class
D

extends
C
{

}




The final modifier:

If you want to prevent classes from being extended, you can use the
final

modifier t
o indicate that class is final and cannot be a parent class.


The abstract modifier:

Abstract classes are like regular classes with data and methods,
but you cannot create instances of abstract classes using the
new

operator.
An abstract
class is

declared
with the keyword
abstract

and may or may not
contain abstract
methods.
If a class contains an abstract method, then the class must be declared as
abstract class.
An abstract method is a method signature without implementation. Its
implementation is provide
d by its subclasses.

The difference between interfaces and
abstract classes is that abstract class can contain fields that are not
static

and
final

and
also can contain implementation methods.


6.
4.3.
Dynamic Binding

in Java
: In Java, all messages are dyna
mically bound to
methods, unless the method is
final

(means it cannot be overridden; therefore, dynamic
binding serves no purpose)
. Also, if a method is specified as
private

or
static
, then it will
disallow overriding and thus will be statically bound.

In
the following example

(left
column of the table)
, when the
test.fn

is called, the
fn()

method present in the
class B

is
called instead of calling the
fn()

method in
class A

due to dynamic binding
.

class A

{

void fn()

{ System.out.println("a.fn"); }

}

cla
ss B extends A

{

void fn()

{ System.out.println("b.fn"); }

}

public class Binding

{


public static void main(
String[]
args
)


{ A test = new B();


test.fn();


}

}

class A

{

public String var = "Class A";


void p()


{System.out.println("a.p");}

}

class
B extends A

{

public String var = "Class B";


void p()


{System.out.println("b.p");}

}

public class Binding1

{


public static void main(
String[]
args
)


{


A a = new A();


A b = new B();


a.p();


b.p();


System.out.println(a.var);


S
ystem.out.p
rintln(b.var
);


}

}

Output

b.fn

Output

a.p

b.p

Class A

Class A


It could be observed from these examples that
dynamic binding

is used when the
compiler is not sure which method to call during compile time. Methods that are inherited
could be overridden b
y the subclass and thus the compiler is not sure which method to
call at compile time.
Static binding

is applied for static methods
,
member variables

and
private methods
.



6.
4.4.
Overloading

in Java
:

Overloading in Java could be done by having different
signatures for a single method.
Java, similar to other languages does handle overloading
at compile time.

Here, when an overloaded method is invoked, its signature or the
appropriate arguments matching is done at compile time. But, if the method that is
in
voked is an instance method, then checking can be done only at runtime, using dynamic