Understanding Abstraction and Encapsulation
Understanding Abstraction and Encapsulation
Abstraction allows one to collect instances of entities into groups in which their common
attributes need not be considered.
Two kinds of abstractions in programming languages are process abstraction and data
abstraction.
The concept of process abstraction is one of the oldest.
All subprograms are process abstractions because they provide a way for a program to
specify that some process is to be done, without providing the details of how it is to be done.
Process abstraction is crucial to the programming process.
The ability to abstract away many of the details of algorithms in subprograms makes it
possible to construct, read, and understand large programs.
All subprograms, including concurrent subprograms, and exception handlers, are process
abstractions
Encapsulation
Encapsulation is a grouping of subprograms and the data that they manipulate
Advantages of encapsulation
Data Hiding: The user will have no idea about the inner implementation of the class. It
will not be visible to the user that how the class is storing values in the variables. He only
knows that we are passing the values to a setter method and variables are getting
initialized with that value.
Increased Flexibility: We can make the variables of the class as read-only or write-only
depending on our requirement. If we wish to make the variables as read-only then we
1
have to omit the setter methods like setName(), setAge() etc. from the above program or
if we wish to make the variables as write-only then we have to omit the get methods like
getName(), getAge() etc. from the above program
Reusability: Encapsulation also improves the re-usability and easy to change with new
requirements.
Testing code is easy: Encapsulated code is easy to test for unit testing.
Information hiding
Information hiding is the term used for the central principal in the design of programmer-defined
abstract data types.
1. By providing a virtual computer that is simpler to use and more powerful than the actual
underlying hardware computer.
2. The language provides facilities that aid the programmer to construct abstractions.
When information is encapsulated in an abstraction, it means that the user of the abstraction
a. does not need to know the hidden information in order to use the abstraction,
b. is not permitted to directly use or manipulate the hidden information even if desiring to
do so.
Subprograms
Type definitions
2
Abstract Data Types
Encapsulation of the whole in such a way that the user of the data object cannot
manipulate data objects of the type except by the use of operation defined.
An abstract data type is simply an encapsulation that includes only the data representation
of one specific data type and the subprograms that provide the operations for that type.
An instance of an abstract data type is called an object.
Object-oriented programming is an outgrowth of the use of data abstraction.
3
A benefit of information hiding is increased reliability. This is because clients cannot
change the underlying representations of objects directly, either intentionally or by
accident, thus increasing the integrity of the object
Design Issues
A facility for defining abstract data types in a language must provide a syntactic unit that
can encapsulate the type definition and subprogram definitions of the abstraction
operations
Concurrent Pascal, Smalltalk, C++, and Java directly support abstract data types
Some design issues beyond encapsulation are whether the kinds of types that can be
abstract should be restricted, whether abstract data types can be parameterized, and what
access controls are provided, and how such controls are specified
Language examples
Ada
o Ada provides encapsulation facilities that can be used to simulate abstract data
types, including the ability to hide their representations.
o The encapsulation constructs in Ada are called packages.
o Each package contains two parts.
o First, is the specification package, which provides the interface of the
encapsulation
o Second, is the body package, which provides the implementation of the entities,
named in the specification.
o The user can choose to make an entity visible to clients or provide only the
interface information.
Modula-2
o The modules of Modula-2 are similar to the packages of Ada, so they provide a
similar level of support for abstract data types
o The primary difference between the two is that in Modula-2, all types whose
representations are hidden in modules must be pointers.
4
C++
o Unlike, Ada and Modula-2, which provide encapsulation that can used to simulate
abstract data types, C++ provides the class, which more directly support abstract
data types
o The data defined in a class are called data members; the functions defined in a
class are called member functions.
o Classes may contain both hidden and visible entities.
Java
o Java’s support for abstract data types is similar to C++
o There are however a few differences, such as, all user-defined data types in Java
are classes and all objects are allocated from the heap and accessed through
reference variables and the support for abstract data types in Java can only be
defined in classes
o Java also includes packages as one of its encapsulation constructs.
Some languages that provide for abstract data types: Ada: packages; C++, Java, Visual Basic:
classes.
Encapsulation by Subprograms
The ability to define subprograms is fundamental to all programming languages. Subprograms
can be viewed as abstract operations on a predefined data set. A subprogram represents a
mathematical function that maps each particular set of arguments into a particular set of results.
5
2. Signature(also known as proto type) giving the number of arguments ,their order,
data type of each as well as number of result their order, and data type of each
3. The action performed by the subprogram
Subprogram Implementation
A subprogram is implemented using the data structure and operations provided by the
programming language. The implementation is defined by the subprogram body, consists of
local data declaration defining the data structure used by sub program and statements
defining the actions to be taken when subprogram is executed. The declaration and
statements are usually encapsulated so that neither the local data nor statements are accessible to
user of the subprogram: The user may only invoke the subprogram with a particular set of
arguments and receives the output results
The interface with the user (the calling program) is accomplished by means of arguments and
returned results.
6
call that creates it and returns that destroys it. To construct a particular activation of a
subprogram it is required to split in two parts:
A static part: Also known as code segment made with the help of constant and executable code.
It should be invariant during execution of a subprogram and so a single copy may be shared by
all activation
A dynamic Part: Known as activation record made with the help of parameter, function results
and local data some other point like temporary storage areas, return point.
The size and structure of activation record for a subprogram can be find out at translation time.
Subprograms associate a name with a sequence of processing instructions in a way that the
statements can be reused at different points in the program by calling the subprogram name. For
example:
The subprogram above computes the circumference of a circle given its radius. The subprogram
is a function because it returns a value.
Reuse is the most obvious benefit of defining a subprogram but subprograms also provide a form
of process abstraction. They encapsulate programming language statements and hide
implementation. The code inside a subroutine is safe from outside influences. Code outside of a
subprogram can't modify local variables in a subprogram or transfer control to statements inside
a subroutine except through the entry point. Subprograms also increase the level of abstraction in
a program. For example, the code on the right below is more abstract than the code on the left:
7
return 2 * r * 3.1415;;
}
The subprogram circumference() is an abstraction of the mathematical formula for calculating
the circumference of a circle. It allows the programmer to calculate the circumference of a circle
without worrying about the details of the computation. The code on the right is easier to
understand and maintain because it is at a higher level of abstraction. Programs that are easier to
understand also tend to be more reliable.
Type Definitions
Type definitions are used to define new data types. They do not define a complete abstract data
type, because the definitions of the operations are not included.
These statements will be processed at translation time and the type of key1 and key2 will be set
to integer.
struct rational_number
8
Chapter Six: Abstraction II
Inheritance
Inheritance is a mechanism in which one class acquires the property of another class. For
example, a child inherits the traits of his/her parents. With inheritance, we can reuse the fields
and methods of the existing class.
In Java, when an "Is-A" relationship exists between two classes we use Inheritance The parent
class is termed super class and the inherited class is the sub class The keyword "extend" is used
by the sub class to inherit the features of super class. Inheritance is important since it leads to
reusability of code.
Types of Inheritance
1. Single Inheritance: One class extends another class (one class only).
2. Multiple Inheritance: One class extending more than one class. Java does not support
multiple inheritance.
9
The derived class becomes the base class for the new class.
10
Inheritance and Controlling Access
You control access to variables, classes, functions, and methods using access control attributes.
When using inheritance, understanding how access control works is important.
Protected - available only to the class that defines it and to any subclasses of that class.
Polymorphism
Polymorphism is a OOPs concept where one name can have many forms. For example, you
have a smartphone for communication. The communication mode you choose could be anything.
It can be a call, a text message, a picture message, mail, etc. So, the goal is common that is
communication, but their approach is different. This is called Polymorphism.
Polymorphism is the ability of an object to take on many forms. The most common use of
polymorphism in OOP occurs when a parent class reference is used to refer to a child class
object. Any Java object that can pass more than one IS-A test is considered to be polymorphic. In
Java, all Java objects are polymorphic since any object will pass the IS-A test for their own type
and for the class Object.
It is important to know that the only possible way to access an object is through a reference
variable. A reference variable can be of only one type. Once declared, the type of a reference
variable cannot be changed. The reference variable can be reassigned to other objects provided
that it is not declared final. The type of the reference variable would determine the methods that
it can invoke on the object.
11
A reference variable can refer to any object of its declared type or any subtype of its declared
type. A reference variable can be declared as a class or interface type.
Example
Now, the Deer class is considered to be polymorphic since this has multiple inheritance.
Following are true for the above examples −
When we apply the reference variable facts to a Deer object reference, the following declarations
are legal −
Example 1
Animal a = d;
Vegetarian v = d;
Object o = d;
All the reference variables d, a, v, o refer to the same Deer object in the heap.
12
Example 2 : Think of a superclass called Animal that has a method called animalSound().
Subclasses of Animals could be Pigs, Cats, Dogs, Birds - And they also have their own
implementation of an animal sound (the pig oinks, and the cat meows, etc.):
class Animal {
public void animalSound() {
[Link]("The animal makes a sound");
}
}
class Pig extends Animal {
public void animalSound() {
[Link]("The pig says: wee wee");
}
}
class Dog extends Animal {
public void animalSound() {
[Link]("The dog says: bow wow");
}
}
Now we can create Pig and Dog objects and call the animalSound() method on both of them:
class Animal {
public void animalSound() {
[Link]("The animal makes a sound");
}
}
class Pig extends Animal {
public void animalSound() {
[Link]("The pig says: wee wee");
}
}
class Dog extends Animal {
public void animalSound() {
[Link]("The dog says: bow wow");
}
}
class MyMainClass {
public static void main(String[] args) {
Animal myAnimal = new Animal(); // Create a Animal object
Animal myPig = new Pig(); // Create a Pig object
Animal myDog = new Dog(); // Create a Dog object
13
[Link]();
[Link]();
[Link]();
}
}
Function Overloading: When there are multiple functions with same name but different
parameters then these functions are said to be overloaded. Functions can be overloaded by
change in number of arguments or/and change in type of arguments.
Operator Overloading: C++ also provide option to overload operators. For example, we can
make the operator (‘+’) for string class to concatenate two strings. We know that this is the
addition operator whose task is to add two operands. So a single operator ‘+’ when placed
between integer operands , adds them and when placed between string operands, concatenates
them.
Example 3:
// CPP program to illustrate
// Operator Overloading
#include<iostream>
class Complex {
private:
public:
14
// This is automatically called when '+' is used with
Complex res;
return res;
void print() { cout << real << " + i" << imag << endl; }
};
int main()
[Link]();
Output:
12 + i9
In the above example the operator ‘+’ is overloaded. The operator ‘+’ is an addition operator and
can add two numbers(integers or floating point) but here the operator is made to perform
addition of two imaginary or complex numbers.
15
#include <bits/stdc++.h>
class base
public:
void show ()
};
public:
void show ()
};
//main function
int main()
base *bptr;
derived d;
bptr = &d;
16
//virtual function, binded at runtime (Runtime polymorphism)
bptr->print();
bptr->show();
return 0;
Output:
print derived class
show base class
Method Overriding
One of the advantages of inheritance is that a subclass inherits all of the public and protected
methods of its superclass. Sometimes though, a subclass needs to change the functionality
defined in the superclass. Overriding is the technique of redefining an inherited method. When
you override a method, use the override keyword. The redefinition must have the same number
of parameters as the original (inherited) definition and its return type must be the same as the
original return type.
The benefit of overriding is: ability to define a behavior that's specific to the subclass type, which
means a subclass can implement a parent class method based on its requirement.
If subclass (child class) has the same method as declared in the parent class, it is known as
method overriding in Java. In other words, If a subclass provides the specific implementation of
the method that has been declared by one of its parent class, it is known as method overriding.
17
Usage of Java Method Overriding
The method must have the same name as in the parent class
The method must have the same parameter as in the parent class.
There must be an IS-A relationship (inheritance).
The return type should be the same or a subtype of the return type declared in the original
overridden method in the superclass.
The access level cannot be more restrictive than the overridden method's access level. For
example: If the superclass method is declared public then the overridding method in the
sub class cannot be either private or protected.
Instance methods can be overridden only if they are inherited by the subclass.
A subclass within the same package as the instance's superclass can override any
superclass method that is not declared private or final.
A subclass in a different package can only override the non-final methods declared public
or protected.
Let's understand the problem that we may face in the program if we don't use method overriding.
18
[Link] Vehicle{
2. void run(){[Link]("Vehicle is running");}
3.}
4.
[Link] Bike extends Vehicle{
6. public static void main(String args[]){
7. //creating an instance of child class
8. Bike obj = new Bike();
9. //calling the method with child class instance
10. [Link]();
11. }
12. }
Output:
Vehicle is running
Problem is that we have to provide a specific implementation of run() method in subclass that is
why we use method overriding.
In this example, we have defined the run method in the subclass as defined in the parent class but
it has some specific implementation. The name and parameter of the method are the same, and
there is IS-A relationship between the classes, so there is method overriding.
[Link] Vehicle{
2. //defining a method
3. void run(){[Link]("Vehicle is running");}
4.}
5.//Creating a child class
[Link] Bike2 extends Vehicle{
7. //defining the same method as in the parent class
8. void run(){[Link]("Bike is running safely");}
19
9.
10. public static void main(String args[]){
11. Bike2 obj = new Bike2();//creating object
12. [Link]();//calling method
13. }
14. }
Output:
Consider a scenario where Bank is a class that provides functionality to get the rate of interest.
However, the rate of interest varies according to banks. For example, SBI, ICICI and AXIS
banks could provide 8%, 7%, and 9% rate of interest.
20
1. //Java Program to demonstrate the real scenario of Java Method Overridi
ng
2. //where three classes are overriding the method of a parent class.
3. //Creating a parent class.
4. class Bank{
5. int getRateOfInterest(){return 0;}
6. }
7. //Creating child classes.
8. class SBI extends Bank{
9. int getRateOfInterest(){return 8;}
10. }
11.
12. class ICICI extends Bank{
13. int getRateOfInterest(){return 7;}
14. }
15. class AXIS extends Bank{
16. int getRateOfInterest(){return 9;}
17. }
18. //Test class to create objects and call the methods
19. class Test2{
20. public static void main(String args[]){
21. SBI s=new SBI();
22. ICICI i=new ICICI();
23. AXIS a=new AXIS();
24. [Link]("SBI Rate of Interest: "+[Link]()
);
25. [Link]("ICICI Rate of Interest: "+[Link]
());
26. [Link]("AXIS Rate of Interest: "+[Link](
));
27. }
28. }
Output:
Can we override java main method? No, because the main is a static method.
21
Using the super Keyword
When invoking a superclass version of an overridden method the super keyword is used.
Example
class Animal {
public void move() {
[Link]("Animals can move");
}
}
class Dog extends Animal {
public void move() {
[Link](); // invokes the super class method
[Link]("Dogs can walk and run");
}
}
public class TestDog {
public static void main(String args[]) {
Animal b = new Dog(); // Animal reference but Dog object
[Link](); // runs the method in Dog class
}
}
Output
Animals can move
Dogs can walk and run
22
Method Overloading
Method overloading is a powerful mechanism that allows us to define cohesive class APIs. To
better understand why method overloading is such a valuable feature, let’s see a simple example.
Suppose that we’ve written a simple utility class that implements different methods for
multiplying two numbers, three numbers, and so on.
If we’ve given the methods misleading or ambiguous names, such as multiply2(), multiply3(),
multiply4(), then that would be a badly designed class API. Here’s where method overloading
comes into play.
implementing two or more methods that have the same name but take different numbers
of arguments
implementing two or more methods that have the same name but take arguments of
different types
The Multiplier class shows, in a nutshell, how to overload the multiply() method by simply
defining two implementations that take different numbers of arguments:
23
public class Multiplier {
public int multiply(int a, int b) {
return a * b;
}
public double multiply(double a, double b) {
return a * b;
}
}
It’s not possible to have two method implementations that differ only in their return types.
To understand why – let’s consider the following example:
24
CHAPTER 7: SEQUENCE CONTROL
Control Structure in a PL provides the basic framework within which operations and data are
combined into a program and sets of programs.
Statements – The statements (conditional & iterative) determine how control flows from
one part of program to another.
Declarative Programming – This is an execution model of program which is
independent of the program statements. Logic programming model of PROLOG.
25
Subprograms – In structured programming, program is divided into small sections and
each section is called subprogram. Subprogram calls and co-routines, can be invoked
repeatedly and transfer control from one part of program to another.
Implicit or default sequence-control structures are those defined by the programming language
itself. These structures can be modified explicitly by the programmer.
eg. Most languages define physical sequence as the sequence in which statements are executed.
Explicit sequence-control structures are those that programmer may optionally use to modify the
implicit sequence of operations defined by the language.
Expression is a formula which uses operators and operands to give the output value.
26
Arithmetic Expressions are evaluated from left to right and using the rules of precedence
of operators. If expression involves parentheses, the expression inside parentheses is
evaluated first
(a + b) > c c<b
The relational operators <, >, <=, >= are given the first priority and other operators (==
and != ) are given the second priority. The arithmetic operators have higher priority over
relational operators. The resulting expression will be of integer type, true = 1, false = 0.
The result of a logical expression is either true or false. For expression involving AND
(&&), OR (||) and NOT(!) operations, expression involving NOT is evaluated first, then
the expression with AND and finally the expression having OR is evaluated.
a) Precedence (Priority)
If expression involving more than one operator is evaluated, the operator at higher level of
precedence is evaluated first.
b) Associativity
27
The operators of the same precedence are evaluated either from left to right or from right to left
depending on the level. Most operators are evaluated from left to right except + (unary plus), -
(unary minus) ++, --, !, & Assignment operators = , +=, *=, /=, %=
Expression Tree
Named after polish mathematician Jan Lukasiewicz, refers to notation in which operator symbol
is placed before its operands.
Cambridge Polish - variant of notation used in LISP, parentheses surround an operator and its
arguments.
(/(*ab)(-cd))
Postfix refers to notation in which the operator symbol is placed after its two operands.
28
AB*, XY-
c) Infix notation
It is most suitable for binary (dyadic) operation. The operator symbol is placed between the two
operands.
1. Basic Statements
i) Assignment Statement
MOVE A TO B. - COBOL
printf, scanf
int age;
Explicit sequence control statement. Used to branch conditionally from one point to
another in the program
int a, b;
Read:
scanf (“%d”, &a);
if (a == 0) goto Read;
y = sqrt(x);
prinf(“%d”, y);
goto Read;
29
v) Break Statement
b) Alternation Type - There are two alternate statement sequence in the program, the
program chooses any of the sequence but not both at same type
c) Iteration Type - Here normal sequence is given to statements but the sequence repeats
itself for more than one time.
II. Explicit Sequence Control - The default sequence is altered by some special statements
end }
b) Conditional Statements
30
elseif (conditional exp) then … statements
c) Iteration Statements
31