Today we're going to talk about object oriented programming, it's one of the most
common ways that software is written these days certainly for things like
applications on desktops and mobile devices. The problem with object oriented programming
though is that it can be quite difficult to get your head around at first 'cause it
uses so many different terms, you talk about objects sending messages to other objects, objects doing
things and you think "Well they're just bits of code, how are they doing anything?" and so on
so it can be difficult to get your head around it.
For Nicholas Wirth, who invented Pascal, once described programs as being algorithms
plus data structures. Now the data structures we can think of as the sort of the data that
our program's manipulating, whatever that might be.
And the algorithm - that's basically the code they we're running to manipulate
that data. One way we can think about this is thinking about something like a simple pong game,
sort of the very early computer games you got back in the seventies. Pong was
a very simple game that you played on your TV. It had - so that's your TV screen - you had
a little bat on this side which one person controlled; you had another bat on
this side that another person controlled and then you had a ball which was a square
block. These literally were square blocks that were filled in on the screen.
So one player could control this and move it up and down, and the other player could control this
to move it up and down, and the ball would bounce between effectively trying to be a sort
of tennis game. The graphics were state of the art for the time, and you can still
find Pongs lying around mainly museums. There's one at the Computer History
Museum down in Cambridge if you were to go and play with it. So the Pong game's very,
very simple but we can use it to sort of think about how the probe would work and
so on and things. So you've got two bats and a ball. So the data for this would be
relatively simple. This paddle or bat over here - you'd need to know where
it is, so you need its position; and we'll call that its y position. And you'd probably keep track
of its x position as well just to make it easier to draw things. And you'd need
the same for this one over here and again for the ball you'd need the ball's x pos.,
and the ball's y position. So that's the data that our program would
represent. It doesn't need anything more than that really. You'd perhaps have some representation
of screen but that'd be handled by the computer, so we'll ignore that for now.
And we'd be able to write programs which would use this data, manipulate it to run
the game. So if a key was pressed, we would change the y position to make the bat go up;
or if a different key was pressed, we'd change this one's y position to make the
bat go down. And we can change this to make the ball sort of bounce off the edge of
the screen, so it looks like the ball's moving around. So we've got to write some code very
simply to do this. So we could say something like,
if he - alright, so we've got to use Q to go up - is pressed then paddle 1 y pos equals paddle 1 y pos plus 1.
And we could do something similar for the going down for the same paddles -
we could write a basic program code that manipulate the variables to move the paddles around.
Then we can redraw the screen; and so we redraw the screen. It looks like the
things are moving. Actually all we've done is change the variables' data and
then redraw the screen. This is OK, and for a simple program like this, this approach
would work and anything else would perhaps be over the top. But often you
would find that you'd have lots of data that you'd want to group together. So for
example with our pong game, we've got a variable to hold the x position; a variable to
hold the y position; a variable to hold the ball's x position; a variable to
hold the ball's y position; and so on.
And we might actually say we're talking a lot of the time about points on things.
So we actually want to group them together. So we can use in various programs that have the
facility to group things together as what we call a data structure. And we can then refer to this
position either as a whole, so you can set the position to be the same as
another position; or we can refer to the individual things inside it. So we can
pass it into a function, say, to draw the paddle, just passing the whole position in there;
but if you want to update one of the values, we can just update that specific
value about the y position that we want to manipulate. But there's still a slight issue with
this sort of approach. It makes it easy to refer to things and we could have lots of
these data structures referring to different things. Rather than having separate
variables here, we could have a position for paddle 1; and a position for paddle 2.
So we can refer to them and have lots of them. We can have one data structure which we can then have
many different things for. So we can actually group the data together, which is quite useful.
But the problem with all of this is that the date is completely open and we can
write code anywhere in our program that can manipulate it. For a simple program like
Pong, having the data open is not a problem. Your program is probably not
gonna be more than a few hundred lines long. As the program grows, you're writing
something bigger, then you have lots of files accessing the data and you might change some
things and forget to update part of the program.
So for example, you might update one part of the program to only allow ten
entries rather the hundred and something, but the other part of the problem still
expects a hundred, and so it writes over the end, walks all over memory that's used for something else.
That's how you get a crash; your program won't work. So, with object oriented programming we turn things on
their heads slightly. Rather than thinking of the program in terms of the code we write and
how it modifies the data, we think rather in terms of objects. So, what would an
object be? Well, using our Pong
example - the objects in this game would be - well we've got two paddles in here; so we'd
have objects that would represent the paddles; and we've got another object
here, which is the ball. So we can sort of see what might be an object in a program. But
the other thing we need to think about,
rather think about writing code that manipulates the data, we need to think
about what these objects can do. What operations can we perform on them?
So for example, on our paddle, we might have operations which make it move up. We might
have an operation that make it move down. And that would be the same for
both paddles. And we could ask the object to perform that operation based on input from
the keyboard. So the ball object would be similar. Rather having operations to
move it up to move it down, we just have an operation says update your position.
We let the ball itself work out how its going to move around the
screen. The other thing we might have is an operation to detect whether the ball
has collided with a paddle. In this case, we'd say to the ball, Have you collided with
this other object? So we'd have the two objects working together to work out
whether they've collided. Now I've described that and I've talked about objects
working with each other; objects having operations. How does this all fit down to
the way it works with a computer? Well, to do that, we need to think about what an
object is. And actually, an object is made up of three things. So let's look at the paddle
as an example to start with, and we'll think about the ball in a minute. It's got some
state. And that's things like its x position and its y position. But you
might also if you - taking this further - you might have to be like the speed associated
with it as well. And they'll just be numerical values, perhaps integers,
floating point numbers, depending on the system
they're using. There could also be other objects, or we could build an object out of
other objects, but that's gonna be advanced. We'll look at that later on.
So what we've got here is no different from the data structures we talked about earlier.
We've got some data and we've encapsulated it together, and we can refer to it as a
whole. The other thing that makes it different is that we also have the
operations, and these are the things that the object can do. So if you think about our
paddle, we said it would be able to move up, and we said it would be able to move down.
We also said that you might be able to draw it on the screen so we'd have a
draw operation as well. We might have other operations that we need to make the program work,
but these aren't things that we're necessarily going to want do to the object like making it move up
or down. So we might have to have operations in ours to get its position. So we might have
a get position operation. And that might be used, say, by the ball object we can
detect whether it's collided with it or not. And it's having these operations which
makes a difference between a simple data structure and an object. We think about
the state as being the center of the object. So we've got that state. That's
our x position and our y position. We'll keep it simple for now for the paddle. When we think
about things in an object oriented way, we say, No, there's a defined interface that can
manipulate this data. And so you have this sort of ring fence around the data.
So you've got this sort of move up operation, the move down, the draw operation and the
get position operation. And the only way this data here can be accessed or
manipulated by calling these operations. And these create what we call the
interface to the object. You can get its position, which will give you an xy
coordinate. We'll have more to have it return that. You can draw it, and you'd perhaps have to give it
the screen you'd want it to be drawn on. You can get it to move down, and you can get it to move up.
and so we now write our programs
not in terms of manipulating the data, but in terms of telling this object to
move up or to move down. What actually happens is that when the move up operation is
performed, there's a bit of code that we specify here which updates the y
variable and then it returns back to whatever called it to continue working.
So it's actually
a way of thinking about, and a way of structuring, the program.
[Offscreen] Would it be fair to say that's a small program in its own right?
Yes; I mean, that's one way you could think about it. The object is a small self-contained program
that's in its own right. So it's got a move up, and a move down, it can be drawn
and you get its position. And then you write another self-contained program for the
ball, and that would perhaps have a similar state, but it would have different operations
associated with it. So an object is actually made up of three things. We've seen the state; we've
seen the operations; but the third thing we have is actually not part of the
object as such. But we also have identity. And this is simply saying that we can
have many objects of the same type. So we can have one paddle, like this; but we
can also - and I'll draw a smaller one for speed - we can also have another one with
its state and the operations around it. And this can represent the other paddle. So we've got
two objects with the identical interfaces: one to represent the paddle on the left;
one to represent the paddle on the right. So the only thing that can
alter the data is the operation on the object of a particular identity. So if we wanted to access it,
we say to an object with this identity, perform this
operation; and that would then go and modify the state of that object.
As I'm sure you've guessed we'd have another type of object to represent the
ball, which should also have an x and a y position. And it would have a different set of
operations around it. So, some of them might be similar. Things like, we might have
a draw operation. But we might have a collide operation instead, and then this time
update positions - that's really got an increase speed operation as well -
let's have a speed value in there. The two objects that represent the paddle of the
same type. They have the same state associated with them, the same operations
associated with them. But this one is of a different type. It's got different state -
it's got an xy position and speed, and it also has a different set of operations
associated with it. And of course it has its own identity, and if we wanted to, we could have two balls
in the game. And generally, in most object oriented languages, when we write these things,
we define what we call a class, which is basically the blueprint for building
objects that it specifies, what operations they have; and provides the
code for those operations. Even though it acts on each individual object, it also
specifies how the data is stored and so on. And then when we create an object, we
create a new one with its own identity, with its own state, and then the operations
can perform on that individual object.
[Offscreen] If we come to update our program, you talked about how that can be a problem with structures.
[Offscreen] How's it easier here, then?
Because we've got this defined interface for the object, the
rest of the program doesn't know anything about how that object is
implemented. So it doesn't need to know there's a y coordinate or an x coordinate in there.
All it needs to know is, to make it move up, it invokes the move-up operation on the object; or
invokes the move down to make it move down. The beauty of this is you have lots of
different classes of objects that implement this interface, and then you
can drop in whichever one you want. So you could have a paddle which is wider, which
would just be different class of object, and drop that in. We could have perhaps a
specialist paddle which was two paddles that moved up and down in sync with each other.
And that'd just be a different class of object which you'd drop in inside. And this is part of what we call
inheritance in object oriented programming is one of the things which
can make it really powerful, which we'll look at in another video.
Over a long enough time scale, I think that human level artificial intelligence
is completely inevitable.
Um, if your auntie hangs around for long enough and continues to progress in what it can do...