Object-oriented Design
and Programming
Dr. Frank Edughom Ekpar
[email protected] 1
Classes and Objects: Key Object-oriented Design
and Programming
and Related Concepts (Abstraction,
Encapsulation, Inheritance, Polymorphism,
Overloading, Overriding, Parameter Passing
Mechanism) in Action
2
Defining New Types (Working With Java
Classes).
Abstraction, Encapsulation, Inheritance
and Polymorphism, Overriding and
Overloading in Action.
Java Interfaces.
Enums.
3
Java Classes: Defining New Types
What is a class?
A class is a blueprint or model or pattern or abstraction for
creating objects of a given type. The class encapsulates the
relevant attributes and behaviors of the objects in a single
component. We can use the class keyword to define new
classes. To create an object or instance of a class, we can use
the new keyword. Behaviors are implemented in the methods
of a class while attributes are captured in the data members or
fields. When a class does not implement one or more of it
methods, it can be declared abstract – in which case we
cannot create instances or objects of the class. Abstract
classes can serve as templates for the creation of related
classes. 4
The Core Class
Let us create a class named Core to represent a core or basic
undergraduate student. A Core object has a name, a midterm
score and a final score. We can place it in a package named
rsu.cen.student. The following is one possible
implementation of the Core class.
package rsu.cen.student;
public class Core
{
public Core()
{
name = “”; midterm_score = 0.0; final_score = 0.0;
5
}
public Core(String name, double midterm_score,
double final_score)
{
this.name = name;
this.midterm_score = midterm_score;
this.final_score = final_score;
}
public double grade()
{ return 0.5*midterm_score + 0.5*final_score; }
6
public String getName() { return name; }
private String name;
private double midterm_score;
private double final_score;
}
7
Java Classes: Instantiation, Access to Members
We use the new keyword to instantiate or create
objects of a class. For example,
Core undergraduate = new Core(“Peter”, 90.0, 80.0);
creates a core object named undergraduate with the
name “Peter”, a midterm score of 90.0 and a final
score of 80.0.
We use the dot(.) operator to access class members.
For example, undergraduate.grade(); returns the
grade (85.0) for the undergraduate object – the
student named “Peter”.
8
Java Classes: Constructors
Constructors are special methods or member
functions with the same name as the class and are
used to instantiate (create objects of) the class.
The default constructor is the constructor with no
parameters. In the Core class, the default constructor
is Core();
A class can have as many constructors as required to
efficiently and conveniently implement the features of
the class.
The Core class implements two constructors, namely,
the default constructor and another constructor that
9
accepts a name, midterm and final scores as input.
Java Classes: this
The “this” keyword refers to the current object. It can
be used to differentiate between variables (with the
same names) belonging to the current object and
external variables.
Note the following code in the implementation of the
second Core constructor where this is used to identify
the name, midterm and final score variables belonging
to the current object.
10
Java Classes: this
public Core(String name, double midterm_score,
double final_score)
{
this.name = name;
this.midterm_score = midterm_score;
this.final_score = final_score;
}
The “this” keyword permits us to identify and
reference members of the current object.
11
Inheritance
A new (child or derived) type (implemented in a class)
can be created on the basis of an existing (parent or
super or base or ancestor) type via inheritance. We
can reuse the features of the existing type while
adding only features peculiar to the new type, leading
to efficiency and clearer organization and
maintainability of software. In Java, inheritance is
implemented using the extends keyword. For
example, Grad represents a graduate student and is
derived from Core which represents an
undergraduate student. We have placed both Core
and Grad classes in the same rsu.cen.student 12
Inheritance
package rsu.cen.student;
public class Grad extends Core
{
public Grad() { super(); }
public Grad(String name,
double midterm_score,
double final_score)
{
super(name, midterm_score, final_score);
}
13
public void setThesisScore(double
thesis_score)
{ this.thesis_score = thesis_score; }
@Override
public double grade()
{
return Math.max(super.grade(),
thesis_score);
}
private double thesis_score = 0.0;
} 14
Inheritance: extends and super
Note that the extends keyword appears after the new
(derived, child) class name and before the parent
(super, base) class name.
The super keyword gives us access to the parent class.
It is invoked in the constructors of the new Grad class
to take advantage of the features already
implemented in the constructors of the parent Core
class.
15
Inheritance: @Override
Overriding and Polymorphism
The @Override annotation is used to indicate the
override or re-implementation of methods already
implemented in the parent or super class. This allows
us to realize polymorphism since overridden
methods could behave differently depending on the
class of the object on which they are invoked. For
example, the grade() method in the Grad class
returns the greater of the grade computed by the
parent (super) Core class and the thesis score by
calling the Math.max() method of the Math class. 16
Overloading and Polymorphism
As we saw earlier, overriding involves using a class
hierarchy with the derived or child class re-
implementing or overriding the original method in
the parent, base, super or ancestor class. In contrast,
we can use overloading to re-implement the same
method with different signatures (including
parameter lists) in the same class or even as a set of
static methods with the same name. Overriding is
carried out at runtime while overloading is carried
out at compile time. So overriding is dynamic while
overloading is static. Now let us overload a method
for calculating the sum of a set of numbers. 17
Overloading and Polymorphism
We can get the overloaded methods to behave
differently based on the context (number of
parameters, for example) so this is a form of
polymorphism.
class OverloadingExample
{
int sum(int num1, int num2)
{return num1+num2;}
int sum(int num1, int num2, int num3)
{return num1+num2+num3;}
} 18
StudentDemo : Putting It All Together
Let us practice what we have learned about classes
and inheritance by creating a simple Java program
named StudentDemo.
Launch the Netbeans IDE and select the File→New
Project… menu to create a new Java project named
StudentDemo or something similar as illustrated
below. When the New Project wizard appears, select
Java under the Categories field and click Next> to
continue. On the next page, type in the name of the
project (StudentDemo) and click Finish to create the
19
project.
StudentDemo : Putting It All Together
20
StudentDemo : Putting It All Together
21
StudentDemo : Putting It All Together
22
StudentDemo : Putting It All Together
Now we can add the rsu.cen.student package to our
project. This is the package that will hold our Core
and Grad classes.
Locate and right-click StudentDemo under the
Projects window within the Netbeans IDE as shown.
Then select the New→Java Package… menu to add
the fuo.mce.student package (by typing it in as the
package name and clicking Finish) to the project as
illustrated. Note that a corresponding hierarchy of
folders and subfolders is created for us under the src
23
folder.
StudentDemo : Putting It All Together
24
StudentDemo : Putting It All Together
25
StudentDemo : Putting It All Together
To add the Core class, locate and right-click
rsu.cen.student under the Source Packages field
under the StudentDemo field under the Projects
window within the Netbeans IDE as shown. Then
select the New→Java Class… menu to add the Core
class (by typing it in as the class name and clicking
Finish) to the rsu.cen.student package in the project
as illustrated. Note that a corresponding source code
file – Core.java – is created in the correct
(rsu/cen/student) subfolder under the src folder.
26
StudentDemo : Putting It All Together
27
StudentDemo : Putting It All Together
28
StudentDemo : Putting It All Together
To add the Grad class, repeat the process described
earlier for the Core class, but this time type in Grad
as the name of the class. Note that a corresponding
source code file – Grad.java – is created in the correct
(rsu/cen/student) subfolder under the src folder.
Generally, you can repeat this process to add classes
under any specified package in your project. Without
the IDE, you would have to manually create and add
the source files (Core.java and Grad.java) to your
project.
29
StudentDemo : Putting It All Together
Now type (or copy and paste) the appropriate source
code for the Core and Grad classes shown earlier into
the Core.java and Grad.java source files within the
Netbeans IDE’s code editor. You can access the source
files under the Source Packages field of the project
name (StudentDemo) under the Projects window of
the Netbeans IDE.
30
StudentDemo : Putting It All Together
We would like to use the Core and Grad classes in our
project. For that, we need to import them. In the
StudentDemo.java source file immediately after the
package statement, type in or copy and paste the
following import statements.
import rsu.cen.student.Core;
import rsu.cen.student.Grad;
31
StudentDemo : Putting It All Together
Within the main method (inside the
StudentDemo.java source file), type in the following
lines of code.
Grad graduate =
new Grad("Peter Graduate", 90.0, 80.0);
graduate.setThesisScore(100.0);
System.out.println(graduate.getName() + " scored: "
+ graduate.grade());
Core undergraduate =
32
new Core("Paul Undergraduate", 90.0, 80.0);
StudentDemo : Putting It All Together
System.out.println(undergraduate.getName() + "
scored: " + undergraduate.grade());
Build and run the project. The output should look like
the following.
Peter Graduate scored: 100.0
Paul Undergraduate scored: 85.0
33
Exercise 4
Implement the StudentDemo project as
described in the lecture notes. Change the
formula for calculating the grade (when
implementing the grade() method) in the Core
class by assigning a weight of 30% (0.3) to the
midterm score and a weight of 70% (0.7) to the
final score. What is the output of the program in
this case?
34
Java Interfaces
An interface is an abstract or reference type used to
describe object behaviors in Java programs. Interfaces
are declared using the interface keyword and contain
method signatures or prototypes, constants (static,
final fields) and in newer versions of Java (Java 8 and
above) may contain default and static methods.
Interfaces are implemented by Java classes using the
implements keyword. They cannot be instantiated. A
class may implement more than one interface – in
which case the interface names are contained in a
comma separated list appearing after the implements
keyword. Example: The Player interface is declared35
Java Interfaces
public interface Player
{
void play();
void pause();
void stop();
}
By implication, the method signatures or prototypes
are abstract so there is no need to append the
abstract modifier. Similarly, any declared fields are
static and final.
36
Java Interfaces
public class VideoPlayer implements Player
{
void play() { System.out.println(“Playing…”); }
void pause() { System.out.println(“Paused…”); }
void stop() { System.out.println(“Stopped…”); }
}//Note: Place @Override above each method.
A class that claims to implement an interface must
implement all the non-default methods of the
interface or be declared abstract. Interfaces form a
contract between a class and the outside world that is
37
enforced at build time by the compiler.
Java Interfaces
Interfaces provide us with the opportunity to
simulate multiple inheritance in Java since a class can
implement multiple interfaces while an interface can
extend other interfaces.
38
Java Enums
The enum (abbreviation for enumeration) is used to
represent a group of constants.
Example:
enum Colors
{
RED, GREEN, BLUE
}
The constants are usually in uppercase letters. We can
use the dot(.) syntax to access the elements in an
enum. For example,
39
Colors myColor = Colors.BLUE;
Java Enums
An enum can be used in a switch construct.
For example,
switch(myColor)
{
case RED: System.out.println(“Red Color”); break;
case GREEN: System.out.println(“Green Color”); break;
case BLUE: System.out.println(“Blue Color”); break;
}
40
Parameter Passing Mechanisms
Pass-By-Value and Pass-By-Reference
41
Pass-By-Value and Pass-By-Reference
There are two basic parameter passing mechanisms,
namely, pass-by-value and pass-by-reference.
In the pass-by-value mechanism, a local copy of the
argument (stand-in for a parameter) is made and
used inside the method so that any changes made
inside the method are not propagated back to the
caller.
42
Pass-By-Value and Pass-By-Reference
Strictly speaking, pass-by-value is the only parameter
passing mechanism used in JAVA but the passing of
objects (addresses of objects) as arguments
effectively permits pass-by-reference.
In the pass-by-reference mechanism, a reference
(address) to the object is passed to the method so
that any changes made inside the method are
propagated back to the caller since the contents of
the address are manipulated through the address.
43
Pass-By-Value Example
package passbyvalue;
public class PassByValue
{
public int count = 15;
public static void main(String[] args)
{
PassByValue object = new PassByValue();
System.out.println("Count BEFORE Pass-By-Value
Call: " + object.count);
44
Pass-By-Value Example
increment(object.count); //The method call.
System.out.println("Count AFTER Pass-By-Value
Call: " + object.count);
}
public static void increment(int count)
{
count += 20;
}
}
45
Pass-By-Value Example
The output of the program should look like the
following:
Count BEFORE Pass-By-Value Call: 15
Count AFTER Pass-By-Value Call: 15
46
Pass-By-Reference Example
package passbyreference;
public class PassByReference
{
int count = 15;
public static void main(String[] args)
{
PassByReference object = new PassByReference();
System.out.println("Count BEFORE Pass-By-
Reference Call: " + object.count);
47
Pass-By-Reference Example
increment(object); //The method call
System.out.println("Count AFTER Pass-By-
Reference Call: " + object.count);
}
public static void increment(PassByReference obj)
{
obj.count += 20;
}
}
48
Pass-By-Reference Example
The output of the program should look like the
following:
Count BEFORE Pass-By-Reference Call: 15
Count AFTER Pass-By-Reference Call: 35
49
Pass-By-Value and Pass-By-Reference
Note that after the call using the pass-by-value
parameter passing mechanism, the value of the count
attribute remains 15 as it was originally initialized.
However, after the call using the pass-by-reference
parameter passing mechanism, the value of the count
attribute is incremented by 20 inside the method and
changes to 35 as expected. Consequently, the
changes made to the count attribute inside the
method are propagated back to the caller.
50