Further Object Oriented Programming "FOOP" and Basic Aspects of OOP
Further Object Oriented Programming "FOOP" and Basic Aspects of OOP
1
Object Oriented Programming
Studied so Far
• You will have taken a 1st year module on Object Oriented
Programming, ECS414U, but that only gives a basic introduction
to the general concept of it
• You will have covered more on aspects of Object Oriented
Programming in the 2nd year module on Software Engineering,
but the that module did not concentrate on detailed aspects of
writing code
• Further study of how to write code was in the 2nd year module
Algorithm and Data Structures, but that module did not give
much emphasis on aspects of programming that come under the
principles of Object Oriented programming
• There are many important aspects of Object Oriented
Programming mentioned but not given detailed coverage so far
2
Professional Programmer Requirements
• Do a web search on “coding interviews” to see the sort of
requirements that would be needed for someone applying for a
job as a programmer
• What this means is that part of the interview for a job application
will involve being asked to write some code to solve a problem
• A coding interview often involves writing code by hand, as it is
considered that anyone who has proper understanding of
programming can do that
• Also look at Oracle’s Programmer Certification:
https://education.oracle.com/oracle-certified-professional-java-
se-8-programmer/trackp_357
to see what they regard as necessary to show that you really
are someone who can program in Java, and their own test to
get a certificate to prove you have reached that level
3
Why Can’t Programmers … Program?
• See this link:
https://blog.codinghorror.com/why-cant-programmers-program/
for a famous article on people apply for programming jobs
• This article has been frequently quoted many times since it was
first put up on-line by one of the most famous commentators on
programming, Jeff Atwood
• The claim in it, following observations from others, is that the
vast majority of applicants for programming jobs “can’t write
code at all”
• It states that the majority of Computer Science graduates, when
asked to write some simple code in an interview, cannot do it
• It is for this reason that coding interviews take place
4
Further Object Oriented Programming
• So the main emphasis of the module ECS658U Further Object
Oriented Programming will be on writing actual code
• The emphasis will be on general aspect of writing code, moving
further from what you have studied in the 1st year module
ECS414U Object Oriented Programming
• It will go into more detail on the important aspects of good
quality code, Design Principles and techniques to meet them,
Design Patterns, that were covered in the 2nd year module
ECS505U Software Engineering
• So, where the emphasis of ECS505U was on showing structure
of code using UML diagrams, and using systems that can assist
in code development, ECS658U will concentrate just on writing
small pieces of code
• ECS658U will cover some of the further aspect of Java beyond
what was covered in ECS414U
5
Java
• For many years, Java was the dominant programming
language, the one most commonly used in professional
programming
• Java was seen as the best example of an object oriented
programming language
• Java was developed from a previous programming language
C++ which had been successful because its object oriented
aspects were found to be useful for developing large scale code
• C++ was developed from a previous programming language, C,
by adding the object oriented features
• Java developed further from C++ by taking away its features
that were in conflict with the general principles of object oriented
programming
6
Python
• In recent years, the programming language Python has grown in
use and now challenges Java as the most used language in
professional programming
• Python has also become a common language for initial learning
of programming, in many cases replacing Java
• Although this growth of Python, challenging Java, has been
recent, Python like Java originated in the 1990s
• A big difference between Python and Java is that Python:
– Takes away the need to declare variables before they are
used
– Takes away the need to declare variables as having types
– So lets any method be called on any variable with any
arguments
• This is what makes Python code shorter and simpler
7
Java v Python
• While Python may seem simpler, because it does not have all
the complex aspects involving the use of variable types, that
also makes it harder to use to explain some of the aspects of
object oriented programming
• The use of types, though making code more complex, also
makes it clearer to see how different parts of code interact, and
enables errors to be discovered when the code is compiled
rather than only found out when it is run
• It is important to understand, however, that both Java and
Python are object oriented languages working by methods being
called on variables that represent objects
• So, while we will use Java to write code to illustrate concepts, it
is important to understand that many of the concepts we will
cover are general object oriented ones that apply also to other
programming languages, such as Python
8
Basic Aspects of
Object Oriented Programming
• The most basic aspect of Object Oriented Programming (OOP)
is that it is a way to divide code into parts
• As code becomes more complex, it becomes very hard to
understand how it works if it is not clearly divided into separate
parts, each of which is clearly defined
• What OOP is about is defining a type of object in terms of how it
interacts with other objects
• Interaction is done by calling a method on an object, or passing
it as an argument to a method
• A class gives the code that makes an object of that class do
what it is meant to do
• But you should be able to use an object just knowing it in terms
of how it interacts, not needing to know the details of the code
that makes it work that way
9
WHAT an Object does and
HOW it does it
• So it is important for code to be written in a way that makes a
clear distinction between WHAT an object does, which is how it
interacts with other objects through methods called on it, and
HOW it does it, which is the code inside it that makes the
methods work
• When you write the code for a class to provide objects that do
WHAT they are defined to do, you may decide they need
variables to store data needed to make them work, but those
variables should not be able to be accessed directly by code in
other classes
• If a variable added to provide HOW an object works could be
accessed and changed by code in another object of another
class, then it could no longer be guaranteed that the object
would work only in the way it was defined WHAT it would do
10
Object Content
• One aspect of what an object does is that a method can be
called on it, and it returns something
• A static method is one that is not called on an object, its
definition is what it just what it returns in terms of any arguments
passed to it
• A method which is not static is called an instance method, it
has to be called on an object and what it does is defined in
terms of the content of the object as well as its arguments
• The contents of an object in this case are part of its definition of
WHAT it does in terms of its interaction with other code, and not
the actual variables inside it that store how the content is
represented
• A method may change the content of the object it is called on
• A method may also change the content of objects passed to it
as arguments
11
Generalising Code
• Code should be generalised so that one piece of code can be
used in more than one place
• A class defining objects is an example: you can have several
objects of the same class, and one method which takes an
argument of that class and does something. Having the same
method used to manipulate the different objects, is better than
having to write separate code to manipulate each object
• However, more generalised code can be written that takes
objects of different classes because it only performs actions that
apply to objects of all the classes
• Having one piece of code that works for objects of different
classes is much better than having lots of pieces of code that
are almost identical apart from the classes of objects they take
• Generalised code should not be complicated by having to check
the details of the particular objects it is manipulating
12
Poor Quality Code
• The human user of some code does not need to know the
details of how it works internally, all that is required is that it
produces the right results
• However, code that is correct in that way is still poor quality if it
does not make the clear distinction between WHAT a piece of
code does and HOW it does it and/or if it is not generalised so
there is large amounts of code similar to other parts
• The reason for this is that poor quality code is more likely to
have errors where it is hard to find the errors and correct them
• Real used code often needs to be modified to add new features,
and that is much harder to do if it is poor quality
• Code which is written in a way that limits the interaction between
different parts is much easier to modify either to add new
features or to improve its efficiency
• Code which is generalised means modifying is less hard work
13
Example: Set of Integers
• As an example, suppose you have to write a class called
IntSet that represents a set of integers
• The class works so that if nums refers to an object representing
a set of integers, then nums.contains(n) returns true if the
value stored in the variable n is in the set, and false otherwise
• The method call nums.add(n) means that
nums.contains(n) will return true after it has been called
• The method call nums.remove(n) means that
nums.contains(n) will return false after it has been called
• If nums.contains(n) returns true, then after
nums.remove(n) has been called it should return false, that
is a number is either contained or not, there is no concept of a
number being contained more than once
• How can we implement this?
14
Set of Integers implemented by an
Array of integers (1)
• Consider:
class IntSet {
private int[] array;
public IntSet() {
array = new int[0];
}
16
Set of Integers implemented by an
Array of integers (3)
public boolean add(int n) {
if(!this.contains(n)) {
int[] array1 = new int[array.length+1];
for(int i=0; i<array.length; i++)
array1[i]=array[i];
array1[array.length]=n;
array=array1;
return true;
}
return false;
}
18
A good implementation?
• No, you will have seen in Algorithms and Data Structures that
there are more efficient ways of implementing a set than this
• No, it is not generalised. If you wanted a set of Strings you
would use very similar code. It would be better to have a
generalised class that represents a set of anything rather than
have to have several classes with almost identical codes to
represent sets of different types of objects
• However, it is much better than just using an array directly: the
code which makes use of objects of class IntSet just has
method calls like set1.add(val), set2.remove(val2),
set3.contains(val3) which makes code much clearer than
code which directly uses and changes an array
• You can be sure that the array can’t be set incorrectly to store
one value more than once
• You could change what is inside IntSet to make it more
efficient without having to make changes to code that uses it
19
Arrays are of fixed size
• An array is of a fixed size, once an array has been created its
size cannot be changed
• A variable of an array type which refers to an array of one length
can be set to refer to an array of a different length, that is what
happens to the variable array of type int[] in the code given
• It is important to understand the difference between setting a
variable to refer to a new object and changing the actual object
it refers to
• Rather than replace the array every time the size of the set is
changed, using the array-and-count technique would be more
efficient in time (but not memory)
• Java’s built-in type ArrayList<E> is like an array that can
change its size, underneath it uses array-and-count
• Python code that uses [ and ] for what seem to be arrays is
actually using the equivalent of Java’s ArrayList
20
What a Method Does
• Here are the things a method can do:
– Return a value
– Change what is inside the object it is called on (if the method
is not static)
– Change what is inside an object passed to it
– Perform some external action, for example print something
• A method can do one or more of these things
• However, it is generally best to avoid having a method that does
more than one thing unless they are closely related
• If a method does two separate things, consider how it could be
split into two methods, one to do each
21
External Action Example
public boolean add(int n) {
if(!this.contains(n)) {
int[] array1 = new int[array.length+1];
for(int i=0; i<array.length; i++)
array1[i]=array[i];
array=array1;
System.out.println("Added "+n);
return true;
}
System.out.println("No change made");
return false;
}
25
Changing Objects Passed as Arguments
public boolean addTo(IntSet set, int n) {
if(this.contains(n))
return set.add(n);
return false;
}
26
Getters and Setters
• Suppose you also had:
public int[] getArray() {
return array;
}
public void setArray(int[] array1) {
array = array1;
}
32
Set implemented by an Array (2)
public void add(E n) {
if(!this.contains(n)) {
E[] array1 = (E[]) (new Object[array.length+1]);
for(int i=0; i<array.length; i++)
array1[i]=array[i];
array1[array.length]=n;
array=array1;
}
}
Note that an aspect of Java is that you can’t directly create a new array
with a type variable as its content type, which is why what has to be
done here is new Object[array.length+1] rather than
new E[array.length+1]
33
Set implemented by an Array (3)
public void remove(E n) {
if(this.contains(n)) {
E[] array1 = (E[])(new Object[array.length-1]);
int i=0;
for(; !array[i].equals(n); i++)
array1[i]=array[i];
i++;
for(; i<array.length; i++)
array1[i-1]=array[i];
array=array1;
}
}
39
Efficiency Issues
• As mentioned previously, an important aspect of programming is
being efficient
• This becomes more of an issue with large amounts of data
• In the example of the remove method, the inefficient version
could take up to twice as long to work as the efficient version
• Consider in this case the difference between going through an
array element by element and going through it by continuously
dividing the section being searched into half
• The maximum number of checks of an array of length m is
log2m which is the value v where 2v is m
• So for an array of length 1024 it would be a maximum of 10
checks rather than 1024
• Checking for efficiency requires using much more data than you
can just type in
• Code to produce large quantities of random data for efficiency
checking can be an important issue to consider
40
Recursion
Here is how contains with binary search could be implemented
recursively:
42
Generalised Ordering
• For simplicity, the example code for a set where elements are
stored in order so that contains can be done efficiently went
back to code that only represents a set of integers
• This code has the test array[mid]<n as part of it
• In Java, the symbol < can only be used to compare numerical
values, so it can’t be used in generalised code
• The test array[mid].compareTo(n)<0 is the equivalent in
generalised code
• However, while array[mid].equals(n) could be used for
objects of any type, it is not the case that object of every class
have the method compareTo that can be called on them
• If a class does have a compareTo method, that is called the
natural order of objects of that class
• We can write generalised code for a set of any type of object
which does have the method compareTo, we will look at that
later
43
Overriding Symbols
• In some other programming languages, it is possible to write a
method in a class which means obj1<obj2 could work where
obj1 and obj2 are variables of any class type
• For example, in Python the test obj1<obj2 turns into a method
call obj1.__lt__(obj2) so providing a method __lt__ in a
class in effect overrides the symbol <
• An advantage of this is that it makes the code look simpler
• A disadvantage of this is that as obj1<obj2 results in a method
call, you cannot be sure how efficient code is, as it could involve
some calculation that takes a long time
• Similarly, in Java, obj1==obj2 does not result in a method call,
so you know it is done in one step, whereas in Python,
obj1==obj2 is equivalent to the method call
obj1.equals(obj2) in Java
• The language C++ is similar to Java, but does allow overriding
of symbols
44
Overriding toString
• Although in general Java does not allow symbols to be
overridden by methods, there is one case in Java it does
• It is the symbol +
• In Java, v1+v2 results in toString being called on the object
referred to by v1 and v2 if they are not numerical variables
• If one is numerical, but the other is not, the String equivalent
of the numerical value is joined to the result of calling toString
on the other to produce a new String
• All objects have a method toString, because it is inherited
from Object, but it is always a good idea to write your own
toString method in any class because if toString is not
overridden what it returns does not give a good indication of the
object it is called on
• As explained previously, one reason for being able to print
something that gives a good representation of an object is to
assist in development, helping find where errors occur
45
Overriding toString and equals
• This code would override toString in the Set class given:
public String toString() {
return Arrays.toString(array);
}
• The method toString it uses is not the standard toString
method, but a static method in the class Arrays that Java
provides
• It shows another reason why it would be best to store elements
in a sorted order, because otherwise two objects that are meant
to represent the same set will have a different toString result
• Another issue is overriding equals. All classes have the
method equals as it is inherited from Object, but if it is not
overridden set1.equals(set2) will return true only if set1
and set2 refer to the same object
• We would want set1.equals(set2) to return true if they
refer to separate objects that contain the same contents
46
String method substring
• This might be better code to override toString in the Set
class given:
public String toString()
{
String astr = Arrays.toString(array);
String instr = astr.substring(1,astr.length()-1);
return "{"+instr+"}";
}
• The idea here is that the String to represent a Set should not
be the same as one to represent an array
• So where the previous version would return [3, 7, 8, 9] this
will return {3, 7, 8, 9}
• Note the way it works to remove the [ and ] and replace them
by { and }
47
Constructive and Destructive Methods
• Another important basic thing to understand in Object Oriented
Programming is the distinction between methods that work by
changing objects, and methods that work by creating and
returning a new object representing the change
• A method which works by creating and returning a new object
representing a change is called a constructive method
• A method which changes an object, either the one it is called on,
or one passed to it is called a destructive method
• With a destructive method, when an object is changed, all
variables that refer to that object have what they refer to
changed
• In the example given, the methods work destructively, so a call
set.add(val) changes the actual object that set refers to,
you don’t assign set to what it returns
• Note that substring works constructively on a String
48
Constructive Version of add
public Set<E> add(E n) {
if(!this.contains(n)) {
E[] array1 = (E[]) (new Object[array.length+1]);
for(int i=0; i<array.length; i++)
array1[i]=array[i];
array1[i]=n;
return new Set<E>(array1);
}
return new Set<E>(array);
}
In this case, it always returns a new object, even if the method does not
cause a change to the set. The reason for this is that otherwise you
would not know whether set2=set1.add(val) results in set2
referring to what set1 refers to or to a separate new object
49
Private Constructor
• The constructive version of add needs another constructor that has
to be added to the class:
private Set<E>(E[] array1) {
array = array1;
}
• As explained previously, a public constructor for a Set which
takes an array as an argument and sets the Set’s array to the same
array is not a good idea, because then other code can change what
is in the array, and that breaks the important principle that an object
should only be changed by methods called on it, or passing it as an
argument to a method
• The point about a private constructor is that it can only be called
by code inside its own class, so it can safely take arguments that
would cause problems if the constructor could be called anywhere
50
The Set code was to illustrate concepts
• We don’t really need to write code that implements a set, because
Java provides built-in code which does that
• Java’s standard collection code is mutable, meaning objects work by
having methods that change them rather than methods that create
and return new collection objects
• The class IntSet and then Set were given here not because you
would need to write this code professionally, but because it works to
give examples of various aspects of OOP that apply more generally
to writing code
• Implementing Set in a way that means any change to the set has to
be done by completely replacing its internal data by new data is very
inefficient, and is not how Java’s own code does it
• You will have seen in the Algorithms and Data Structure module
better ways of implementing collections, we will give further
consideration of how it is done in Java’s own code later
51
OOP in General
• When Object Oriented Programming is first taught, it tends to be
illustrated by objects which represent things in the real world where
you are writing code to model them
• In that case, the methods called on objects will represent real world
actions that the things in the real world can do, or have done to them
• Good representation then means you should avoid having methods,
or ways of changing data inside objects that would change them in a
way that the real world things they represent could not do
• As we have shown here, classes can also be used to implement
objects which are needed for more abstract aspects of coding
• The main point is to clearly divide code into separate parts, given by
classes, with a clear definition of how objects interact
• Limiting the way objects can interact makes code easier to
understand, and easier to modify
52
Inheritance
• An important aspect of Object Oriented Programming we have not
covered much yet is inheritance
• What inheritance means is that if you want to write a class of objects
that is similar to an existing class, instead of copying its code, you
should define the new class as a subclass of the existing class
• Then, all that is needed in the new class are those aspects of it
which differ from the existing class
• If the new class has some extra methods, and extra data needed for
them, you can put them in the subclass
• You don’t need to write a method if it should work in exactly the
same way as the same method in the existing class, it just inherits it
• If the method with the same name should behave differently, you do
write it and that is called overriding the method
• The overriding method can call the method from the existing class,
and also do something extra
53
Simple Example of Inheritance
A subset of IntSet:
class IntRangeSet extends IntSet {
private int limit;
public IntRangeSet(int limit) {
super();
this.limit=limit;
}
public void add(int n) {
if(n<=limit && n>=0)
super.add(n);
}
public int getLimit() {
return limit;
}
}
54
Dynamic Binding
• A constructor call new IntRangeSet(100) will create an object that
works just like an IntSet object, except that if you call add(n) on it
when n is less than 0 or greater than 100 it won’t change
• So you don’t have to rewrite all the code from IntSet, and if IntSet
was changed to a more efficient representation, the class
IntRangeSet would share that change
• A variable of type IntSet can be set to refer to an object created by
the IntRangeSet constructor, but the actual class of the object
remains IntRangeSet
• If we have a variable set of type IntSet which was assigned to an
object created by new IntRangeSet(100) then a call
set.add(150) will not add 150 to the set because a method call
uses the code from the actual class of an object that the variable it is
attached to refers to, this is dynamic binding
• However, the method getLimit() cannot be called on a variable of
type IntSet even if it refers to an object of actual type IntRangeSet
55
Polymorphism (1)
• Here is a simple method:
static boolean inBoth(int n, IntSet s1, IntSet s2) {
return s1.contains(n) && s2.contains(n);
}
• One or both parameter variables could be set to refer to an object of
type IntRangeSet, so you don’t have to write another method to
perform the same task for IntRangeSet objects
• Here is another simple method:
static void addAll(int[] list, IntSet set) {
for(int i=0; i<list.length; i++)
set.add(list[i]);
}
• If set is set to refer to an object of type IntRangeSet than values
in list outside its range will not be added to it
• That is polymorphism: code which works differently depending on
the actual type of an argument, but only because of dynamic binding
56
Polymorphism (2)
• Here is another polymorphism method:
static IntSet chooseAdd(int n, IntSet s1, IntSet s2) {
if(s1.contains(n)) {
s2.add(n);
return s1;
}
else if(s2.contains(n)) {
s1.add(n);
return s2;
}
else
return s1;
}
• Here, if an assignment to a call is made:
IntSet cset = chooseAdd(val,set1,set2);
then cset would refer to either what set1 refers to or what set2
refers to, so it may or may not have actual type IntRangeSet if
just one of set1 and set2 refers to an object of that actual type
57
Polymorphism (3)
• So polymorphism is another way of generalising code, you can
have one piece of code that works in different ways depending on
the actual type of the object passed to it
• An important part of good quality code is to try and avoid writing
parts of code that are very similar to each other, and instead use
just one piece of generalised code
• Polymorphism should not involve checking the actual type of
objects referred to by variables of a super class type, as that
makes code more complex
• Also code that involves checking actual types would need to be
modified for any new subclass that was introduced later
• Interface types are another form of polymorphism
• Interface types only have method signatures, a class defined as
implements an interface type must provide the method code
• A variable of an interface type can refer to an object of any class
that implements it, that includes a subclass of a class declared as
implements it 58
Actual and Apparent Type
• As noted, a variable of type IntSet can refer to an object whose
actual type is IntRangeSet
• Suppose variable cset of type IntSet has been set to an object
whose actual type is IntRangeSet, can we then make a call
cset.getLimit()?
• No, the only methods we can call on a variable are those in the
type of the variable, which is its apparent type
• Here is code we could use:
int maxVal = Integer.MAX_VALUE;
if(cset instanceof IntRangeSet) {
IntRangeSet rset = (IntRangeSet) cset;
maxVal = cset.getLimit();
}
• The idea is to set maxVal to the highest integer that can be added
to the set referred to by cset
59
Type Checking and Casting
• Integer.MAX_VALUE is the maximum value a variable of type
int can hold, we will look at this issue later
• A test of the form svar instanceof RType returns true if the
actual type of the object that svar refers to is RType or a subtype
of Rtype, otherwise it returns false
• It is used when svar is of a supertype of Rtype
• As is an expression of the form (RType) svar, which gives a
value that a variable of type Rtype can refer to
• (RType) svar is described as casting svar to a subtype of its
type, it only works when svar refers to an object whose actual
type is RType or a subtype of RType
• It should not be considered as “converting” to RType what svar
refers to, if it was called when what svar refers to was an object
not of type Rtype then it would throw an exception of type
ClassCastException
• So, you can create a reference to an object of its actual type if that
needs to be done, but you cannot change an object’s actual type60
Design Principles
• With inheritance, some caution is needed, as code could work
unexpectedly if you did not realise that a variable refers to an
object of a subclass
• For example, you might think chooseAdd(val,set1,set2)
leads to val being in both set1 and set2 if it is initially in one of
them, but that would not be the case if one is an IntRangeSet
and val is greater than its limit
• This caution is known as the Liskov Substitution Principle
• Using inheritance to modify code rather than changing the actual
code is a way of meeting the Open Closed Principle
• Writing generalised code that uses dynamic binding rather than
checking the actual type of an object passed to it is an aspect of
the Dependency Inversion Principle
• The Single Responsibility Principle is about making code easy
to understand and modify by dividing it into separate parts
• The Interface Segregation Principle takes this further by limiting
the possible interaction between different parts of code 61
What we have covered so far
• We have gone through a long set of detailed slides, but nearly
everything in them was covered in previous modules
• To what extent is what we have covered so far obvious because
you already knew it from the previous modules?
• Experience suggests there are many aspects of Object Oriented
Programming that were taught, but not properly picked up by most,
so they need to be covered again
• It helps to look at several examples of an aspect to understand it
properly
• It helps a lot to write and run your own code to experiment with the
aspects and make sure you really do understand them
• The slides and comments on them have briefly mentioned further
aspects that we need to cover so that you can truly claim you have
a good understanding of Object Oriented Programming
• We will use Java to illustrate aspects, but emphasise aspects that
are general so apply in some way whatever language you use
62
Java’s Collection Framework
• We have considered how to implement an object representing a
set, because that works as a simple example to demonstrate
various concepts
• For real programming, you should use Java’s class HashSet<E>
or TreeSet<E> which implement the interface Set<E>
• Similarly, ArrayList<E> and LinkedList<E> implement the
interface List<E>
• Also, HashMap<K,V> and TreeMap<K,V> implement the
interface Map<K,V>
• In the first year OOP module, only ArrayList<E> was covered in
detail, and not in a way that made detailed explanation of the use
of type variables
• To claim to be someone who knows how to program in Java, you
would be expected to know about all of these and be able to use
them, so we will go over them in detail
63
Sorting
• You never really need to write your own code to sort a collection,
because Java and other programming languages provide built-in
code to do it
• You need to know how to use Java’s built-in generalised sorting
code, its two versions, one of which use the method compareTo
inside objects which are elements in the collection being sorted,
the other using the method compare called on a Comparator<T>
object
• Sorting also works well as a simple example to illustrate many
general concepts of algorithms
• For example, how to use recursion, which skilled programmers
should be able to use easily, but many who have just learned to
program find a difficult concept to pick up and use
• Sorting shows how with large amounts of data, the algorithm used
can make a huge difference in the time taken
• Also, understand the difference between manipulating a collection
destructively and constructively, which sorting can illustrate 64
LispList<E>
• A class called LispList<E> will be introduced
• It is not a built-in class in Java, it is used because it is a convenient
way of illustrating many important aspects of programming, in that
way it is like Set<E> as it was in these slides rather than as Java’s
built-in Set<E> interface
• It is named after the programming language called Lisp, one of the
earliest programming languages, which introduced the concept of
functional programming that has in recent years become more
widely used industrially
• One aspect of LispList<E> is to help teach the basic way of
thinking recursively and using recursion
• Another is to illustrate the clear distinction between an abstract
data type given by a class and the concrete data structure inside
it used to implement it
65
Java Versions
• Java has gone through many versions since it was introduced,
though each new version is added in a way that means it will still
run code written for previous versions
• Java 5 was when type variables were introduced, a major
modification that meant if Java is taught properly even introductory
programming needed to be changed, as anyone who claims they
have learnt even basic Java should know about programming
using type variables
• What was introduced in Java 8 was another major change in Java
that anyone who claims they have learnt how to program in Java
should know about
• Java 8 introduced Lambda Expressions as a way that allows
Java to be used in a functional programming style
• See http://ocpj8.javastudyguide.com/ for an on-line book that
covers Java up to Java 8
• We won’t cover every detail of Java that is in this book, but we will
cover the important aspects that you need to know 66
Functional Programming in Java
• The main aspect of functional programming is to have variables
that can refer directly to functions
• A function is like a method that takes some arguments and returns
something
• This is different from the the emphasis of calling methods on
objects and methods working by changing objects rather than
creating and returning new objects
• A functional style of programming can be given in Java by having
objects whose only role is to have a single method called on them
that just creates and returns a new object
• Java 8 introduced a way of writing Java code which is much neater
as it hides the object oriented aspects underneath that implement
the functional style of programming
• Another important aspect of some functional programming is lazy
evaluation, which means delaying running the code of a method
until its result is actually needed, Java 8 introduced a new type,
Stream, which works in this way 67
What we will cover
• Although this module is called “Further Object Oriented
Programming”, what it covers is actually basic underlying aspects
of Object Oriented Programming
• The code we will look at will be small and abstract, not large scale
code divided into many classes, and classes whose task is to
represent real world things – this was covered in the Software
Engineering module
• What we are covering, however, will help you write better large
scale code, because we are concentrating on the techniques
needed to do that, such as how to write more generalised code
and how to avoid poor quality code that can be hard to modify and
more likely to contain errors and what can lead to security
problems
• Concentrating on abstract code means we won’t have time to look
at the code for Graphical User Interface
• Another important aspect of coding we will only be able to look at
briefly is concurrency: code working simultaneously 68
Design Patterns
• We will look at Design Patterns, which were mentioned briefly in
Software Engineering
• A Design Pattern is a name given to a general way of structuring
code that deals with particular issues
• An example is the Decorator design pattern, which is a way of
adding new aspects to the way an object works different from
using inheritance
• Another example is the Factory design pattern using a Factory
Object, which means creating a new object by calling a method on
an object designed for that purpose rather than directly making a
constructor call
• The techniques of Design Patterns tend to be not obvious to those
who have just learnt to do Object Oriented Programming, but are
widely used by more experienced programmers, and do lead to
neat and well structured code
• Design Patterns provide a vocabulary for talking about code
structure 69
Lab Work
• This is a practical module, you will be given regular lab work to do
• The lab work will be about writing code
• It will be about writing small pieces of code, consisting of a few
classes and some test code
• Real professional code would be much larger, with an emphasis on
considering how you could divide code into many classes and
define the classes in terms of WHAT they do before implementing
them and so providing HOW they do it
• However, the techniques covered in the labs will be things that you
would need to know about and be able to use in large scale
professional code
• An important thing here is that the best way to learn programming
tactics and understand them properly is to practice then by writing
and running your own code that makes use of them
• So although marks will be given for the labs that contribute to the
final module mark, the main purpose of them is to help you learn,
rather than to give you marks like an exam 70