- As we've seen classes/objects can be used like structs to group
together hunks of data as a new type, but there actually many other
important properties.
- As you may have noticed, programs can sometimes get
complicated. Object Oriented programming is a way of organizing
programs to try to manage this complexity. It does this com
allowing classes to hold not just data, but also the methods that
operate on the data.
- In structured/procedural programming, you have functions as the
basic units of the program, and they operate on the data. In OOP,
the basic units are the objects, and they contain the code that
tells those objects how to behave.
- Let's look at an example
class Player {
int row,col;
int facing;
public void turnLeft() {
facing = (facing+1)%4;
}
- This code looks just like the player class you already wrote for
the lab, but notice how there is a method that is included inside
the definition of the class. Also note how the word static
disappeared.
- We could have done this the old way of course. Take a look at
this for comparison:
class Player {
int row, col;
int facing;
}
public static void turnLeft(Player p) {
p.facing = (p.facing+1)%4;
}
- The Object Oriented version does not have any different
functionality. It is simply a way of organizing things. The next
few weeks will be about the advantages of this system.
- The method above is called a member-method, because it is a part
of the class itself.
- See how the member method modifies the facing variable. It just
does it with out mentioning a variable of type Player. So how does
it know which player it is that is turning left? That is
made clear in the call:
Player one = new Player();
Player two = new Player();
one.turnLeft();
two.turnLeft();
Compare that to:
Player one = new Player();
Player two = new Player();
turnLeft(one);
turnLeft(two);
So we see that when we call the member method, the way we call it
determines which player it is being called on.
- I like to think of it as, when calling a member method
(sometimes called invoking the member method), there is an automatic
first argument that doesn't go inside the parentheses.
- When we mention a variable in the class (called a member field
in Java), the method knows that it is the one that is inside the
object that called the method.
- Another way to think of it is that every object has its own copy
of the method inside it, and you call it by first mentioning the
object, then using the dot to get inside the object, and then
mentioning the method name. Thus when the method is running, when a
variable is mention, it first looks locally inside the method. If
it doesn't find it, it then looks in the wider scope of the object
to find it there.
Diagram belongs here
- Assuming a turnRight() method similar to turnLeft(), What is the
output of the following:
Player one = new Player();
Player two = new Player();
one.facing = 0;
two.facing = 0;
turnLeft(one);
turnRight(two);
System.out.println("one: " + one.facing + " two: " + two.facing);
- Each method call modifies just the object that invoked it.
- Now, notice how I initialized the objects in the code above? Of
course, that only did 1/3 of the job. The whole thing is kind of
messy and ugly. Too many lines of code. We could make a special
function, that's what I did:
Player one = new Player();
Player two = new Player();
initPlayer(one,20,0,0);
initPlayer(two,20,39,2);
...
- But now we know we could add that method to the class to better
organize it:
class Player {
class Player {
int row,col;
int facing;
public void initPlayer(int r, int c, int f){
row = r;
col = c;
facing = f;
}
public void turnLeft() {
facing = (facing+1)%4;
}
...
Player one = new Player();
Player two = new Player();
one.initPlayer(20,0,0);
two.initPlayer(20,39,2);
- This is common enough that we have a special way of initializing
objects using a method called a constructor.
- The constructor is a member method that has the SAME NAME AS THE
CLASS. It has no return type.
- Arguments to the constructor are passed when the object is made:
class Player {
class Player {
int row,col;
int facing;
public Player(int r, int c, int f){
row = r;
col = c;
facing = f;
}
public void turnLeft() {
facing = (facing+1)%4;
}
...
Player one = new Player(20,0,0);
Player two = new Player(20,39,2);
- Nice how it cleans up the code we see in main, isn't it?
- In Java we can overload methods the same way we can overload
functions in C++. This is common when it comes to constructors
because we might not have all the information we need to initialize
an object:
class Player {
class Player {
int row,col;
int facing;
public Player(int r, int c, int f){
row = r;
col = c;
facing = f;
}
public Player() {
//defaults
row = 0;
col = 0;
facing = 0;
}
}
- Just like C++, Java selects the version of the method to call
based on the number and type of the arguments.