ECS658 U01 Introduction Part 3

You might also like

Download as pptx, pdf, or txt
Download as pptx, pdf, or txt
You are on page 1of 14

Further

Object Oriented Programming


“FOOP”
Introduction
and Basic Aspects of OOP
ECS658U
Matthew Huntbach
matthew.huntbach@qmul.ac.uk

Part 3
1
Changing Objects Passed as Arguments
public boolean addTo(IntSet set, int n) {
if(this.contains(n))
return set.add(n);
return false;
}

• This illustrates an example of a method that changes an object


passed to it as an argument rather than changing the object it is
called on
• If this was in class IntSet, a call set1.addTo(set2,val) could be
made, and that call would not change the object that set1 refer
to, but it could change the object that set2 refers to

2
Getters and Setters
• Suppose you also had:
public int[] getArray() {
return array;
}
public void setArray(int[] array1) {
array = array1;
}
• Would that be good?
• No!
• This is an illustration of the general principle that you should not
add getter or setter methods unless what they do is part of the
definition of WHAT an object does rather than just HOW it does it
• Also array is declared private so it cannot be get or set directly

3
Why not Getters and Setters?
• If you could call nums.setArray(val) where val is of type int[], you
could change array to refer to [4,8,7,8,5] for example, if val refers
to the array [4,8,7,8,5].
• The code for IntSet ensures no number is repeated in the array,
but here 8 is repeated. That means that if nums.remove(v) where
v is set to 8 is called, nums.contains(v) will still return true when it
should then return false.
• If array was not declared as private, then nums.array=val would
have the same effect.
• Suppose nums represents the set {4,5,7,8,} then
val=nums.getArray() could set val to [4,5,7,8], but it could also set it
to [7,5,8,4] because nothing in the code ensures the integers are
stored in order of value
• If array was not declared as private, then val=nums.array would
have the same effect.
4
Variables Referring to Objects
• Suppose nums represents the set {4,5,7,8} and val=nums.getArray()
did set val to [4,5,7,8], that could still lead to a problem later on
• If after that val[2]=1 happens, the array changes to [4,5,1,8].
• That would also cause the array inside the set referred to by nums
to change to [4,5,1,8]
• The point is that return array does not create a copy of the array
referred to by the variable array, it returns a reference to the same
actual array.
• Similarly, when val is assigned to that, it does not create a copy of
the array, it sets val to refer to the same array object.
• So as val[2]=1 changes the array that val refers to, that means it
changes the array that array inside the IntSet object refers to
• Proper understanding of the concept of variables referring to
objects is a crucial aspect of OOP that many seem to get wrong

5
Objects should only be changed by method
calls defined as changing them
• This is a key issue
• We have defined IntSet by its methods add, remove and contains
• If an object of type IntSet gets changed, what a call of contains on it
will return can change
• The only way an object of type IntSet should be able to be changed
is by calling add or remove on it
• If an IntSet object could be changed by an assignment like val[2]=1
which does not even seem to be linked to the IntSet object, that
can cause serious problems to code
• It makes it much harder to understand how the code works, much
harder to prove that it will work correctly, and much harder to make
modifications to it and know they won’t cause other problems

6
Contents in terms of WHAT and HOW
• The important thing to understand here is the difference
between the contents of an object when considering WHAT it
does with the contents of an object when considering HOW it is
implemented
• The contents of an IntSet in terms of WHAT it does is a
collection of integers without any integer being repeated, as
defined by the methods add, remove and contains
• The contents of IntSet in terms of HOW it is implemented here is
an array of integers, but that is not a good way to implement it
• A good way of programming is to be able to write some code
quickly that implements the methods that define WHAT an
object of a class does so that code making use of objects of that
class can be written, and suggestion on any changes needed
• Then be able to change the code that is HOW it is represented
to make it more efficient but without that change causing any
changes in code using it, apart from less time or memory use
7
Set implemented by an Array (1)
Here is how to write generalised code in Java:
class Set<E> {
private E[] array[];
public Set<E>() {
array = (E[]) new Object[0];
}
public boolean contains(E n) {
for(int i=0; i<array.length; i++)
if(array[i].equals(n))
return true;
return false;
}
Note it is array[i].equals(n) not array[i]==n, this is an important issue
we will cover later

8
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]

9
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;
}
}

Note, this is inefficient as it checks element up to the position


where n is removed, and then unnecessarily checks them again
10
Set implemented by an Array (4)
More efficient version:
public void remove(E n) {
E[] array1 = (E[])(new Object[array.length-1]);
int i=0;
for(; i<array.length; i++)
if(array[i].equals(n))
break;
else
array1[i]=array[i];
if(i==array.length)
return;
i++;
for(; i<array.length; i++)
array1[i-1]=array[i];
array=array1;
}
An important issue of being a good programmer is being able to
think of issues like this
11
Generalisation Using Type Variables (1)
• This show an example of an extra feature of Java that we will
cover: the use of type variables in declaring a generalised class
• So, for example
Set<String> words = new Set<String>();
which can also be written as
Set<String> words = new Set<>();
declares a variable that represents a set of String objects and
Set<Account> accs = new Set<>();
declares a set that represents a set of Account objects where
Account is another class that has been put together and so on,
and these variables are set to empty sets.
• Then if acc is of type Account, you can call accs.add(acc), and if str
is of type String you can call words.add(str) and so on, but
accs.add(str) or words.add(acc) would cause a compiler error

12
Generalisation Using Type Variables (2)
• A set of integers needs to be started as
Set<Integer> nums = new Set<>();
because you cannot do Set<int>
• Integer is a built-in wrapper type for objects representing
integers, we will look into this issue in more detail later
• A set that can store objects of any type can be started by
Set<Object> anything = new Set<Object>();
but also by
Set anything = new Set();
which is known as a “raw type”
• Old versions of Java could only work like this, but it is not good
as it means you can’t ensure a set can only contain objects of a
particular type
• Python still works like this
• More on the use of type variables to come later
13
Representation Invariant
• A set in the code that has been given is represented internally
by an array, and the array has to be one where no element is
stored more than once
• So, the representation technique is not just the type of variables
used internally, but also a rule that limits what they can store
• Code to implement actions in the object that cause changes to it
must be written in a way that ensures they keep to that rule
• The word representation invariant is used to mean such a rule
• A more efficient way to represent a set of integers would be to
insist they are stored in numerical order, then the method
contains would work more quickly, as it could used binary search
to check whether an integer is in the array
• So that would then be an additional aspect of the
representation invariant and the method add would need to be
modified to keep to it
14

You might also like