Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                

Object Oriented Programming: DR O.Rifi

Download as pdf or txt
Download as pdf or txt
You are on page 1of 32

Object Oriented

Programming
with

Java

Dr O.Rifi
Organized by S.Zaayter
Content

Contents
1 Compiled versus Interpreted Programming Languages 1

2 Basic types and instructions 1

3 Static Methods 3

4 Arrays 4

1 Compiled versus Interpreted Programming Languages


Compiled vs Interpreted PLs

• Processor can execute machine code.

• Compiled languages are converted directly into machine code (e.g. C language).

• Compiled languages need a "build" step - they need to be manually compiled first. You need to
"rebuild" the program every time you make a change.

• Interpreters will run through a program (written in an interpreted language) line by line and
execute each command (e.g. Prolog, PHP, Javascript).

• Java is a semi-interpreted language. You write a program in Java language, then you compile
it with Java compiler javac which converts your code into bytecode , finally you run your
program with java interpreter.

2 Basic types and instructions


First Program

• An executable Java program consists of a method (function) main within a class structure.
public class MainClass {

public static void main(String[] arg) {


System.out.println("Hello World");
}
}

• The instruction System.out.println("Hello World") would print the string (word) Hello World
to the console along with a new line. To stay on the same line we should use print instead of
println .

• The instruction System.out.printf is used in the same way as printf in C.

11
Primitive Data Types

• Logical values: boolean (1 bit) ( true , false ).

• Integer: byte (1 byte), short (2 bytes), int (4 bytes), long (8 bytes) (e.g. 25l ou 25L).

• Floating point numbers: float (4 bytes) (e.g. 12.5f ou 12.5F), double (8 bytes).

• Character: char (2 bytes) (e.g. ’a’ ), Unicode encoding.


long g = 25L;
float t = 12.5f;

• Note: Java Types are independent of machine architecture. It is not the case of C.

Control Structures

• Control Structures if-else , while , for , ... are used in the same way as in C.
public static void main(String[] args) {
int n = 2;
int p = 10;
int power = 1;
for (int i = 1; i <= p; i++) {
power *= n; // power = power * n;
}
System.out.printf("%d to the power %d = %d\n",n,p,power);
// or
System.out.println(n+" to the power "+p+" = "+power);
}

Reading from from Standard Input

• Scanner class allows to read data from standard input.


public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("Give n: ");
int n = sc.nextInt();
System.out.print("Give p: ");
int p = sc.nextInt();
// ...
}

• Output
Give n: 2
Give p: 10
2 to the power 10 = 1024

22
Example: solving Quadratic Equations
public static void main(String[] args) {
double a, b, c;
System.out.print("Give coefficients a, b, c: ");
Scanner sc = new Scanner(System.in);
a = sc.nextDouble(); b=sc.nextDouble(); c=sc.nextDouble();
double delta;
delta = b * b - 4 * a * c;
if (delta < 0) {
System.out.println("No solution");
} else if (delta == 0) {
System.out.printf("Double root = %.2f%n", -b/(2*a));
} else {// delta > 0
double r = Math.sqrt(delta);
System.out.printf("x1 = %.2f, x2 = %.2f%n",
(-b+r)/(2*a), (-b-r)/(2*a));
}
}

3 Static Methods
Static Method (1)

• Static Methods in Java correspond to functions in C. Format:


public static returnType methodName (ListOfParameters){
methodBody
}

• returnType could be void or any primitive data types.

• methodName the name of the method.

• ListOfParameters could be empty or list of data types followed by variables.

• methodBody any sequence of instructions.

Static Method (2)


Example of a method that given two parameters n , p of type int computes and returns the
values of n to the power p .
public class MainClass {

public static int power(int n, int p) {


int pn = 1;
for (int i = 1; i <= p; i++) {
pn = pn * n;
}
return pn;
}

public static void main(String[] args) {

33
int value = power(2,10);
System.out.printf("%d\n",value);
}
}

4 Arrays
Arrays(1)

• We can define an array of integer as follow: int[] tab;

• The latter code is just a variable declaration without any memory allocation.

• To allocate memory to an array we use the following: tab = new int[10];

• We can define an array and initialize its values in one instruction. Example
int[] tab = {4, 6, 9, 3, 5, 8, 2, 7, 1};
//the latter code is similar to:
int[] tab = new int[9];//tab has length 9
tab[0]=4;
tab[1]=6;
//...

Arrays(2)

• The length (size) of an array is fixed once the array is created.

• This length could be accessed by using tab.length

• An array could be passed as a parameter to a method.

• A method return type could also be an array.

Simple Sorting Method (1)


public class ArrayExamples {
public static void sort(int[] tab) {
for (int i = 0; i < tab.length - 1; i++) {
for (int j = i+1; j < tab.length; j++) {
if (tab[i] > tab[j]) {
//swap values
int aux = tab[i];
tab[i] = tab[j];
tab[j] = aux;
}
}
//now tab[i] is the smallest value from i+1 to tab.length
}
}

44
Simple Sorting Method (2)

public static void main(String[] args) {


int[] tab = {4, 6, 9, 3, 5, 8, 2, 7, 1};
sort(tab);
for (int i = 0; i < tab.length; i++) {
System.out.print(tab[i] + " ");
}
System.out.println();
}
}

Output
run:
1 2 3 4 5 6 7 8 9

Method for appending 2 arrays (1)


public static int[] append(int[] t1, int[] t2) {
//Creating an array that will store values from t1 and t2
int[] tab = new int[t1.length + t2.length];
//Storing t1 in tab
for (int i = 0; i < t1.length; i++) {
tab[i] = t1[i];
}
//Storing t2 in tab after t1
for (int i = 0; i < t2.length; i++) {
tab[i + t1.length] = t2[i];
}
//Returning tab from the method
return tab;
}

Method for appending 2 arrays (2)


public static void main(String[] args) {
int[] tab1 = {1,2,3,4};
int[] tab2 = {5,6,7};
int[] tab = append(tab1, tab2);
//Arrays.toString(tab) will return a String containing the values of tab
System.out.println(Arrays.toString(tab));
}

Output
run:
[1, 2, 3, 4, 5, 6, 7]

55
Content

Contents
1 Classes & Objects 1

2 Sending Messages 2

3 this: The current Object 3

4 Encapsulation 4

1 Classes & Objects


Class Definition
In order to define complex data type in Java (Point with integer coordinates, Date with three
integers representing day, month and year, ...) we use class definition. (In C, we use struct .)
Example:
public class Point {
int x;
int y;
}

In C, we may define the following structure:


struct Point {
int x;
int y;
};

Using a Class
We may use the latter definition of Point class in order to declare a variable of type Point :
public static void main(String[] arg) {
Point p;
}

in C:
void main(){
struct Point *p;
}

In the above two cases the variable p is just a future reference (pointer) to an object Point which is
not yet created (allocated a memory space).

Creating Objects
To create an Object in Java, we should use the new keyword.
public static void main(String[] arg) {
Point p;
// p is an instance of Point, Point() is a constructor call.

61
p = new Point();
}

in C:
void main(){
struct Point *p;
p = (struct Point*) malloc(sizeof(struct Point));
}

In C, we may define a variable of type Point without using a pointer so the object is immediately
created ( struct Point p; ). In Java, all variables (except those having primitive type) are only
references.

Accessing Object’s Fields


Once an object is created, we can access its fields by using the dot notation:
public static void main(String[] arg) {
Point p;
p = new Point();
p.x = 1;
p.y = 2;
Point q = new Point();
q.x = p.x + 1;
q.y = p.y + p.x;
System.out.printf("q = [%d, %d]\n", q.x, q.y);
}

Output:
run:
q = [2, 3]

Object references
Once an object is created, it could be referenced by more than one variable.
public static void main(String[] arg) {
Point p = new Point();
p.x = 1;
p.y = 1;
// q refers the same object as p
Point q = p;
q.x = 2;
q.y = 2;
System.out.printf("p = [%d, %d]\n", p.x, p.y);
}

Output:
run:
p = [2, 2]

72
2 Sending Messages
Instance Methods (1)
To a class, we can add methods that define the behaviour of its instances (Objects).
public class Point {
int x;
int y;

void move(int dx, int dy) {


x += dx;
y += dy;
}

double distance() {
return Math.sqrt(x * x + y * y);
}
}

Instance Methods (2)


public static void main(String[] args) {
// New object of type Point is created. its x and y initialised to 0
Point p = new Point();

// We send to p a message (calling method move) with parameters 3, 4


// so 3 will be added to its x and 4 to its y
p.move(3, 4);

System.out.printf("p = [%d, %d]\n", p.x, p.y);


System.out.printf("%.2f\n", p.distance());
}

Output:
run:
p = [3, 4]
Distance = 5.00

3 this: The current Object


this: refers the current object (1)
The this keyword used in method body will refer the object calling that method.
public class Point {
...
void move(int dx, int dy) {
this.x += dx;
this.y += dy;
}
...
}

83
public static void main(String[] args) {
...
// this in move is a reference to p
p.move(3, 4);
...
}

this: refers the current object (2)


In some cases, the use of this is mandatory. Example: when parameters have the same names
as fields.
public class Point {
...
void putAt(int x, int y) {
this.x = x;
this.y = y;
}
...
}

4 Encapsulation
Encapsulation Principle: problem
Consider the following class Time :
public class Time {
int hour, min, sec;
}

It is supposed now that an object of type time should have values of its fields within a certain range
in order to be considered logically valid. That is, hour should be between 0 and 23, min and sec
should be between 0 and 59.
But from this class we can create logically invalid object:
public static void main(String[] args) {
Time t = new Time();
t.hour = 23;
t.min = 65; // min should have value >= 0 and < 60
t.sec = 45;
}

Encapsulation Principle: solution (1)


To overcome such situations, Java allows to limit the visibility of class fields to its methods only,
by using the private modifier.
public class Time {
private int hour, min, sec;
}

Now, all fields of class Time are inaccessible from outside the class. That is, the following code will
cause a compile error.

94
public static void main(String[] args) {
Time t = new Time();
t.hour = 23; // can’t access field hour from t because it is private
}

Encapsulation Principle: solution (2)


To access private fields of an object, we should provide its class by setter and getter methods. The
setter methods would control then values assigned to fields.
public class Time {
private int hour, min, sec;

public int getHour(){


return hour;
}
public void setHour(int hour){
if(hour >= 0 && hour < 24){
this.hour = hour;
}else {
this.hour = 0; // Otherwise, put some default value
}
}
}

Encapsulation Principle: solution (3)


Now, we can access fields by using the provided methods.
public static void main(String[] args) {
Time t = new Time();
t.setHour(23);
System.out.printf("Hour = %d\n", t.getHour());
...
}

The first advantage of the Encapsulation Principle: Control The Set.

Encapsulation Principle: Hiding the Implementation (1)

• When fields are private, the class implementer could change the class representation (fields
definition) and adapt the public methods without affecting the client user ( main method or any
other method in any other class).

• Suppose now that we want to change the representation of class Time from 3 int variables
(hour, min, sec) to one int variable secMed (seconds since midnight). (The class will become
more efficient in term of space complexity. That is, each object will occupy 4 bytes instead of
12 bytes in memory).

Encapsulation Principle: Hiding the Implementation (2)

10
5
public class Time {
private int secMid;

public int getHour(){


return secMid / 3600;
}
public void setHour(int hour){
if(hour >= 0 && hour < 24){
int secWithoutHours = secMid % 3600;
secMid = secWithoutHours + hour * 3600;
}else {
secMid = secMid % 3600;
}
}
}

11
6
Content

Contents
1 Constructors 1

2 Methods Overloading 3

3 Class Variables and Class Methods 3

4 Constants in Java 4

5 Objects Destruction 6

1 Constructors
Default Constructor
A class constructor is a particular method that has no return type and has a name which is exactly
the same as the class name. A class that does not have a constructor will be implicitly provided by a
default one. The following class
public class Point {
private int x, y;
}

is similar to the one below


public class Point {
private int x, y;

public Point(){

}
}

Other Constructor
We may write a specific constructor with parameters allowing fields initialisation
public class Point {
private int x, y;

public Point(int x, int y){


this.x = x;
this.y = y;
}
}

In this case, the default constructor will no longer exists.


public static void main(String[] arg) {
Point p = new Point();// Compilation error
// rather, we should use the constructor with parameters
Point p = new Point(3, 4);

12
1
}

Many Constructors
We may have many constructors in the same class that differ by the type and/or by the number of
parameters
public class Point {
private int x, y;

public Point(int x, int y) {


this.x = x; this.y = y;
}

public Point() {
this.x = this.y = 0;
}

public Point(Point p) { // copy constructor


this.x = p.x; this.y = p.y;
}
}

Using the this method


We may use the this(...) to call a constructor from within another constructor.
public class Point {
private int x, y;

public Point(int x, int y) {


this.x = x; this.y = y;
}

public Point() {
this(0, 0);
}

public Point(Point p) { // copy constructor


this(p.x, p.y);
}
}

Calling Constructors
We can use any of the three above constructors to create a Point object.
public static void main(String[] arg) {
Point p = new Point();
Point q = new Point(3, 4);
Point t = new Point(q);
System.out.println(t);
}

Output:

13
2
run:
[3, 4]

2 Methods Overloading
Methods Overloading
We may define many methods having the same name but different parameters in the same class.
public class Point {
private int x, y;

public double distance(){


return Math.sqrt(x * x + y * y);
}

public double distance(Point p){ //distance between 2 points


int dx = x - p.x;
int dy = y - p.y;
return Math.sqrt(dx * dx + dy * dy);
}
}

3 Class Variables and Class Methods


Class Variables (1)
Suppose now that fields in class Point are of type double and that we are in need to define a method
equals that tests equality of fields between two points.
public class Point {
private double x, y;

public boolean equals(Point p) {


// return x == p.x && y == p.y;
// theoretically fields should be equal but not computationally
double dx = Math.abs(x - p.x);
double dy = Math.abs(y - p.y);
if(dx < 1.0e-5 && dy < 1.0e-5){// hard coded value
return true;
}
return false;
}
}

Class Variables (2)


public class Point {
private double x, y;
private double eps = 1.0e-5;

public void setEps(double eps){

14
3
this.eps = eps;
}

public boolean equals(Point p) {


double dx = x - p.x;
double dy = y - p.y;
if(dx < eps && dy < eps){
return true;
}
return false;
}
}

Class Variables (3)


Given the last definition of class Point, each object of that class has its own eps (instance variable).
And that may cause some logical problem. Consider the following code:
public static void main(String[] arg) {
Point p1 = new Point(3.0, 4.0);
Point p2 = new Point(3.001, 4.001);
p2.setEps(1.0e-2);
System.out.println(p1.equals(p2)); // false (using eps of p1)
System.out.println(p2.equals(p1)); // true (using eps in p2)
}

Testing equality between two object should be symmetric.

Using the static modifier

• We define eps to be static , that is eps is now a class variable shared by all objects of that
class.
private double x, y;
private static double eps = 1.0e-5;
public static void setEps(double eps){
this.eps = eps;
}

• Class variables exist when the class is loaded into memory, before any object creation.

• Methods that manipulate class variables (static fields) should be defined as static.

• Static methods could never access instance variables (instance fields).

• Static methods could be called from any object but also from the class itself ( Point.setEps(1.0e-2) ).

4 Constants in Java
Using the final modifier
We use the final modifier to make a variable (class or instance variable) constant. That is, once the
variable is given a value, that value could never be changed again.

15
4
public class Person {
private String name; private int age;
private final int yearOfBirth; // can’t initialise with a default value

public Person(String name, int age, int yearOfBirth) {


this.name = name; this.age = age;
this.yearOfBirth = yearOfBirth; // no setter could be defined
}
}

Note: when we create an array ( int[] tab = new int[10] ), we can access its length using the
instruction tab.length . tab is an object of type array of integer and length is a public final
variable (field) which is set once for all when the array is created.

Using the final static modifiers


A static variable could also be final
public class Pixel {
public static final MAX_X = 1024;
public static final MAX_Y ;

static{
// will be executed once the class is loaded.
double res = 3.0/4.0;
MAX_Y = MAX_X * res;
}

...
}

When a static variable is final, we should immediately initialise it or use a static block to define its
value.
A class is loaded when we create the first object or accessing a static variable or method.

Example of static final members

• Math.sqrt(...) : sqrt(...) is static method in class Math

• Math.PI : PI is a public static final variable in class Math representing the value of π.

• Math.E : E is a public static final variable in class Math representing the value of exp.

• System.out.println() :

– System is a class,
– out is a public static final variable in class System representing a PrintStream object
connected to the console,
– println() is an instance method in class PrintStream .

16
5
5 Objects Destruction
Garbage Collector(1)

• In C/C++, programmer is responsible for both creation and destruction of objects. Usually
programmer neglects destruction of useless objects. Due to this negligence, at certain point,
for creation of new objects, sufficient memory may not be available and entire program will
terminate abnormally causing Out Of Memory Errors.

• But in Java, the programmer need not to care for all those objects which are no longer in use.
Garbage collector destroys these objects.

• Garbage collector is best example of Daemon thread as it is always running in background.


Main objective of Garbage Collector is to free heap memory by destroying unreachable objects.

• An object is said to be unreachable if there is no more reference to it.

• Garbage collector is called asynchronously by the Java Virtual Machine (JVM).

Garbage Collector(2)
public static void main(String[] arg) {
Point p1 = new Point(1, 1);
Point p2 = new Point(2, 2);

p1 = new Point(3, 3);


// after the above instruction, point (1, 1) is no more referenced
// GC will remove it from the heap, when more memory is needed.

p2 = null;
// point (2, 2) is no more referenced...

//we can call GC explicitly


System.gc();
}

Method finalize
There is a particular method finalize that each class could define and that the garbage collector
will call on objects before removing them from memory.
public class Point {
private double x, y;

...

public void finalize() {


...
}
}

17
6
Content

Contents
1 Delegation 1

2 Inheritance (Specialisation/Generalisation) 3

1 Delegation
Delegation

• An object o1 instance of class C1 uses the services of an object o2 instance of class C2 – o1


delegates a part of its activities to o2.

• Class C1 uses the services of class C2

– C1 is the client class


– C2 is the server class

• The client class C1 contains a field (attribute) of types C2 (e.g. Class Circle contains a field of
type Point representing its center instead of x & y).
public class Circle {
private int x, y;
private Point center;
private int radius;

Delegation Cont.

public Circle(int x, int y, int radius) {


this.x = x; this.y = y;;
center = new Point(x, y);
this.radius = radius;
}

public void move(int dx, int dy) {


x += dx; y += dy;;
center.move(dx, dy);
}

public double distance() {


return Math.sqrt(x * x + y * y) - radius;;
return center.distance() - radius;
}

18
1
Delegation Cont.
public String toString() {
return String.format("[%.2f, %.2f], %.2f", x, y, radius);;
return center.toString() + ", " + radius;
}
}

Other examples:
public class Set {
private int[] tab = new int[100];

public class Book {


private String title;

Aggregation vs Composition

• Delegation induces a relationship between two classes. It is a "has a" relationship. (A circle
"has a" Point).

• The relationship "has a" is of two type, either it is a composition or an aggregation.

• When an instance of a component (Point) can not be in relation with more than one aggregate
(Circle) and the component has a life cycle dependant of the aggregate, the relationship is said
to be a Composition. (In the above example of the class Circle, the center field is created
within the Circle constructor... When a Circle Object is destroyed the related Point object is
also destroyed.

• When the component has autonomous existence outside the aggregate, the relationship is said
to be an Aggregation. (Example follows).

Aggregation
public class Circle {
private Point center;
private int radius;

public Circle(Point center, int radius) {


this.center = center;
this.radius = radius;
} //...

public static void main(String[] args) {


Point point = new Point(1, 1);
Circle circle = new Circle(point, 5);
System.out.println(circle);
point.move(1, 1);
System.out.println(circle);
}
}

19
2
Aggregation Cont.
The output of the above main method:
run:
[1, 1], 5
[2, 2], 5

So you can see that when the object point has moved, the circle has moved also !
The object point has a life cycle that is independent from the object circle .

2 Inheritance (Specialisation/Generalisation)
Inheritance, Specialisation

• Suppose that we have an application which is in need of services that only some are already
defined by a given class (without necessarily having the code of that class). (E.g, we have the
class Point, but we need GraphicPoint: a point that could be displayed on a canvas)

• A GraphicPoint needs all attributes and operations (methods) that exist in Point but in addition,
it needs a field representing its color, and an operation that performs the drawing.

• Should we rewrite all the code of class Point to define GraphicPoint ? In fact, we can use the
existing class Point to define the class GraphicPoint by using inheritance.

• The relationship induced by inheritance is called "is a" relationship (GraphicPoint is a Point).

Specialisation Cont.
public class Point {
int x, y;

public Point(int x, int y) {


this.x = x;
this.y = y;
}

public Point() {
this(0, 0);
}

public void move(int dx, int dy) {


x += dx;
y += dy;
}

public double distance() {


return Math.sqrt(x * x + y * y);
}

public String toString() {


return String.format("[%d, %d]", x, y);
}
}

public class GraphicPoint extends Point{


private Color color;

public void draw(Graphics g){


g.setColor(color);
g.fillOval(x - 1, y - 1, 3, 3);
}
}

public static void main(String[] args) {


GraphicPoint gp = new GraphicPoint();
gp.move(3, 4);
System.out.println(gp.distance());
gp.draw(...);
}

20
3
Specialisation Cont.

• A class inherits from another using the keyword extends .

• GraphicPoint is a subclass of Point. Point is a superclass of GraphicPoint.

• A subclass inherits all attributes and methods from its superclass. It could define more attributes
and methods.

• Constructors are not inherited but reused.

• A class can extend only one class (Inheritance in Java is not multiple).

• If attributes are privates, they are inherited but not accessible. (Use protected as modifier to
enable access.

• While designing classes, if the superclass exists before the subclasses, the process is called
Specialisation.

• If subclasses exist before the superclass, the process is called Generalisation (Abstraction).

• The inheritance relation is transitive. If C extends B and B extends A, then C inherits all
attributes and methods from B and A.

Methods Overriding
A subclass can override an inherited method. (The method, exactly same signature, is redefined in the
subclass.)
public class A {

public void hello(){


System.out.println("hello");
}

public void display(){


System.out.println("From A");
}
}

public class B extends A {


//changing behaviour
public void display(){
System.out.println("From B");
}
}

A a = new A();
B b = new B();

a.hello(); // −−> Hello


a.display(); // −−> From A

b.hello(); // −−> Hello


b.display(); // −−> From B

Overriding vs Overloading
Do not confuse Overriding with Overloading.
public class A {

public void methodX(int i){...}


}

Overriding

21
4
public class B extends A {

public void methodX(int i){...}


}

B contains only one methodX(int)


Overloading
public class C extends A {

public void methodX(double i){...}


}

C contains two methodX , one inherited with parameter int and the other defined in the class itself
with parameter double.

Overriding with code reuse


A subclass could override a method from its superclass without a complete behaviour change. That
is, the redefined method could use the code of the method of the superclass and adds some other code.
public class GraphicPoint extends Point{

public String toString() {


return super.toString()+", "+ color;
}
}

The Class Object

• Inheritance hierarchy is a tree whose root is the class Object.

• Every class other than Object has a superclass.

• By default, a class that does not extend another class, extends Object implicitly.
public class Point {...}
// same as
public class Point extends Object {...}

• The class Object contains many methods that are inherited by all other classes. Two of these
methods are of interest:

– String toString() method that we override in many classes. If not overridden, it re-
turns the class name followed by "@" followed by a certain hexadecimal text.
– boolean equals(Object o) which by by default returns true iff the parameter and the
current object are the same.

Constructors Reuse
Constructors are not inherited but could be reused in the definition of the subclass’ constructors.
public class Point {
protected int x, y;
public Point (int x, int y) {
this.x = x;
this.y = y;
}
}

public class GraphicPoint extends Point {


private Color color;
public GraphicPoint (int x, int y, Color color) {

22
5
super(x, y); // calls the constructor’s of the superclass.
// The call to super should be the first instruction.
this.color = color;
}
}

Constructors Reuse Cont.

• If a constructor does not have an explicit call to super , the compiler will provide an implicit
call to it without parameters.
public class A {
private int i;
public A (int i) {
super(); // implicit call to the constructor of the class Object.
this.i = i;
}
}

• If a class does not not have a constructor defined explicitly, the compiler will provide a default
constructor calling the super constructor.
public class A {
public A () {
super();
}
}

Constructors Reuse Cont.

• If class C extends B and B extends A, then a call to a constructor of class C chains up a call to a
constructor of B, then a call to a constructor of class A then a call to the constructor of the class
Object. Execution order of constructors is in reverse.
• A constructor of a subclass should call explicitly a constructor of its superclass if the superclass
does not have a default constructor.
public class A {
protected int i;
public A (int i) {
this.i = i;
}
}

public class B extends A {


// if no constructor, compilation error
// if a constructor without call to super with a paramter of type int, compilation error
}

Class and Members Visibility

• We can control the visibility of a class member (attribute or method) by using the following
modifiers:
– public accessible to any other class.
– private accessible only within the class itself.
– protected accessible to any subclass and to any class in the same package.
– package accessible to any class in the same package.
• Two levels of visibility for classes:
– public accessible to any other class.
– package accessible to any class in the same package.

23
6
Final classes and Methods

• When a method is final, it is forbidden to override it in any subclass.


public class A {

public final methodX(...){


...
}
}

• When a class is final, it is forbidden to extend it. (Class String is final.) All methods are
implicitly final.
public final class A {
...
}

24
7
Content

Contents
1 Polymorphism 1

2 Abstraction & Interfaces 3

1 Polymorphism
Upcasting

• Class B that inherits from class A could be considered as a sub-type of the type defined by class
A.

• GraphicPoint is a Point .

• Each instance from class B is also an instance of class A.

• To a variable of type A, it is possible to assign a reference to an object of class B. ( Point p = new GraphicP

• This process is called Upcasting and it is implicit.

• Object is the root of any inheritance hierarchy, so all classes could be upcast to it. ( Object o = new Savin

Upcasting Cont.

• When an object is upcast to a super type, it is seen, by the compiler, as an object of that type,
so only methods defined in the superclass could be called from that object.
public class Point {
public void move(int dx, int dy) {...}
public double distance() {...}
public String toString(){
return String.format("[%d, %d]", x, y);
}
}

public class GraphicPoint extends Point {


public void draw(...);
public String toString(){
return super.toString() + ", " + color;
}
}

public static void main(String[] args) {


Point p = new GraphicPoint(...);
p.move(1, 1);
p.distance();
p.draw(...);
}

Dynamic Binding

• In Point p = new GraphicPoint(...); , Point is the static type of p , and GraphicPoint


is its dynamic type.

• When a method is called, the compiler ensures that this method is defined in the class of the
static type.

25
1
• But, during execution, the method which is executed is the one that is overridden in the class of
the dynamic type (Dynamic Binding).
public static void main(String[] args) {
Point p = new GraphicPoint(...);
p.move(1, 1); // move in Point
p.distance(); // distance in Point
System.out.println(p.toString()); // toString in GraphicPoint
}

Polymorphism

• Upcasting and Dynamic Binding serve to implement the Polymorphism.

• In OOP, Polymorphism is

– the fact that an object of a class could be manipulated as an object of another class (super-
class).
– the fact that the same operation (method) could behave differently according to the dy-
namic type of the caller object.

• Polymorphism is the third characteristic of any OOP language after Encapsulation and Inheri-
tance.

Polymorphism, Example
public class Account {

private String reference;


protected double sold = 0.0;

public void debit(double sum) {


sold -= sum;
}
}

public class SavingAccount extends Account {


...
}

public class CardAccount extends Account {

public void debit(double sum) {


super.debit(sum);
sold -= sum * rate / 100;
}
}

public class Bank {


private Account[] list = new Account[100];
private int nb = 0;

public void add(Account acc) {


list[nb++] = acc;
}

public Account search(String ref){


for(int i = 0; i < nb; i++){
if(ref == list[i].getReference()){
return list[i];
}
}
return null;
}
}

Bank bank = new Bank();


bank.add(new Account("112233"));
bank.add(new CardAccount("223344", ...));
Account acc = bank.search(...);
acc.debit(100); // Polymorphism occurs

26
2
Downcasting

• When B inherits from A, we’ve seen that we can upcast an object of type B to a variable of type
A. ( A a = new B(); )

• Now, we can downcast an object to its dynamic type. ( B b = (B) a; )

• Before downcast an object to a type, we’ve to ensure that this object is of that type.
if(a instanceof B){
B b = (B) a;
}

Otherwise a ClassCastException is thrown to indicate error in your code.

About equals

• Whenever objects of a class we’re defining need to be compared for equality with respect to the
values of their attributes, the method boolean equals(Object o) of the Object class should
be overridden.
public class Point {

private int x, y;

public boolean equals(Object o) {


if(! (o instanceof Point)) {
return false;
}

Point p = (Point) o;
return x == p.x && y == p.y;
}
}

2 Abstraction & Interfaces


Abstract Classes
Classic Example

• An application needs to manipulate different geometric shapes.

• Each shape is defined by its position in the plan.

• each shape could move, compute its perimeter and area.


class Circle

double x, y
double radius

move(double dx, double dy)


area()
perimeter()

27
3
class Rectangle

double x, y
double width, height

move(double dx, double dy)


area()
perimeter()

class Triangle

double x, y
double x1, y1 // v1
double x2, y2 // v2

move(double dx, double dy)


area()
perimeter()

Abstract Classes, Generalization.


Define a superclass that all other classes extend, declare in it common attributes and implement com-
mon methods that have exactly same behavior for all subclasses.
public class Shape {
protected double x, y;

public void move(int dx, int dy) {


x += dx;
y += dy;
}
}

public class Circle extends Shape{


private double radius;

public double area()


return Math.PI * radius * radius;
}

public double area()


return 2 * Math.PI * radius;
}
}

Remarks
• The class Shape has no useful meaning, that is no objects are needed from this class. It is there
just for upcasting and polymorphism.
• Class Shape is an abstract concept, so we can define it as abstract which forbids any object
creation.
• Methods in subclasses having same signature but different behaviors ( perimeter, area ) should
also be defined in class Shape so a Shape variable, whether it refers a Circle or a Rectangle could
call them.
• Such methods should be defined as abstract without any implementation.

Abstract Shape
• The class Shape should look like
public abstract class Shape {
protected double x, y;

public void move(int dx, int dy) {


x += dx;
y += dy;
}

public abstract double perimeter();

public abstract double area();


}

28
4
• Each subclass of Shape should define (override) all abstract methods.

• Example of use
Shape sh = new Shape(...); //Error
Shape sh = new Rectangle(...);
sh.move(1, 1); // executes move in Shape
sh.perimeter(); // executes perimeter in Rectangle, but first the compiler ensures that
// perimeter is defined in Shape.

Java Interfaces

• Abstract classes are there to regroup subclasses belonging to the same family (having common
attributes and common behaviors (methods)).

• What if we want to regroup classes with respect to some behavior only? That is, classes with
no relation but having common behavior.

• E.g. objects of type Rational (number) and objects of type Time have common behavior: they
are all comparable.

• Suppose that we want to implement a sort(...) method that sorts an array of Rationals or an
array of Times, we have to find a structure to which we can upcast Rational and Time.

• Such a structure is called an interface .

Interface Comparable

• Consider the following interface


public interface Comparable {
public int compareTo(Object o);
}

• Interface is like an abstract class, all methods declared are like abstract methods (they have no
implementation).

• The method compareTo should return a negative numbers if current object is less than o, 0 if
current is equal to o and a positive number otherwise.

• When a class implements an interface, it should implement all methods defined in that interface.
Object of this class could be upcast to a variable typed by that interface.
public class Time implements Comparable {
public int compareTo(Object o) {...}
}

Comparable cp = new Time(...);

Interface Comparable, Cont.

• Now, we can implement a sort method that talks to that interface


public static void sort(Comparable[] tab) {
for (int i = 0; i < tab.length - 1; i++) {
for (int j = i + 1; j < tab.length; j++) {
if(tab[i].compareTo(tab[j]) > 0){
Comparable aux = tab[i];
tab[i] = tab[j];

29
5
tab[j] = aux;
}
}
}
}

Interface Comparable, Cont.

• The class Time may look like


public class Time implements Comparable {
int hour, min, sec;

public int compareTo(Object o) {


Time t = (Time) o;
return (hour * 3600 + min * 60 + sec)
- (t.hour * 3600 + t.min * 60 + t.sec);
}
}

• Now, in a main method we can have


Time [] tab = {
new Time(12,45,1),
new Time(11,5,20),
new Time(11,4,0)
};

sort(tab);

• Note that a class can implements many interfaces.

30
6

You might also like