Afrikaans
Akan
Albanian
Amharic
Arabic
Armenian
Azerbaijani
Basque
Belarusian
Bemba
Bengali
Bihari
Bosnian
Breton
Bulgarian
Cambodian
Catalan
Cebuano
Cherokee
Chichewa
Chinese (Traditional)
Corsican
Croatian
Czech
Danish
Dutch
English
Esperanto
Estonian
Ewe
Faroese
Filipino
Finnish
French
Frisian
Ga
Galician
Georgian
German
Greek
Guarani
Gujarati
Haitian Creole
Hausa
Hawaiian
Hebrew
Hindi
Hmong
Hungarian
Icelandic
Igbo
Indonesian
Interlingua
Irish
Italian
Japanese
Javanese
Kannada
Kazakh
Kinyarwanda
Kirundi
Kongo
Korean
Krio (Sierra Leone)
Kurdish
Kurdish (Soranî)
Kyrgyz
Laothian
Latin
Latvian
Lingala
Lithuanian
Lozi
Luganda
Luo
Luxembourgish
Macedonian
Malagasy
Malay
Malayalam
Maltese
Maori
Marathi
Mauritian Creole
Moldavian
Mongolian
Myanmar (Burmese)
Montenegrin
Nepali
Nigerian Pidgin
Northern Sotho
Norwegian
Norwegian (Nynorsk)
Occitan
Oriya
Oromo
Pashto
Persian
Polish
Portuguese (Brazil)
Portuguese (Portugal)
Punjabi
Quechua
Romanian
Romansh
Runyakitara
Russian
Samoan
Scots Gaelic
Serbian
Serbo-Croatian
Sesotho
Setswana
Seychellois Creole
Shona
Sindhi
Sinhalese
Slovak
Slovenian
Somali
Spanish
Spanish (Latin American)
Sundanese
Swahili
Swedish
Tajik
Tamil
Tatar
Telugu
Thai
Tigrinya
Tonga
Tshiluba
Tumbuka
Turkish
Turkmen
Twi
Uighur
Ukrainian
Urdu
Uzbek
Vietnamese
Welsh
Wolof
Xhosa
Yiddish
Yoruba
Zulu
Hey, welcome back.
In the exercise you just finished, you ended up writing a method that printed out a player's
name and health.
Right.
It looked something like this.
Now let's look at that in a slightly different way.
This code actually does the same thing, but we've used local variables to hold onto the
player's name and health.
We can think of these variables as representing the player's current state.
Your method then does something with the player's state, it prints it out.
We can think of that as the player's behavior.
That's kind of cool, but right now the state and behavior are just loosely associated.
It'd be nice to wrap them together.
And that's exactly what classes let us do.
With a class, we can combine variables and the methods together.
Or said another way, we can combine state and behavior together.
Then we can use that class as a template to create objects and fill in the values for
the state.
Here's a player object that represents Larry with a health of 60.
And here's another player object representing Mo with a health of 100.
Notice that each object's state is unique, but they have the same behavior.
Each player can say hello.
So let's recap how that works with Ruby classes that we've already used.
So back over in IRB, let's try out some of these classes and objects.
So we can think of a class as a factory that just churns out objects.
If we had a variable called greeting, for example, to create a string object, we're
used to using the literal, either a double quoted string or a single quoted string.
I'll just say hello.
And if we look at the object's class, well, we have a string class.
The object referenced by the greeting variable was created from the string class.
Now a more explicit way to create a string is to use the string class itself.
We can call the new method on that class and pass in the actual characters.
So we're gonna get exactly the same thing.
We have a string called hello.
We often refer to objects like this as instances because they're instances of the specific
class.
They were created from a class, in this case, string.
Now we've seen that with objects, we can also call methods.
So if I have greeting, I could call reverse, for example, to reverse the string.
Or I could use upcase to uppercase the string.
So that's one string object.
Let's try another one.
In this case, we'll have an object called farewell or a variable called farewell.
And we'll create it using the explicit way.
We'll just pass in goodbye, like so.
So now we've got this string has the characters goodbye.
But we can also call the methods reverse, for example, to reverse it.
And we can call the method upcase to upcase it.
So objects created from the same class have unique state, hello and goodbye, but the same
shared behavior, reverse and upcase.
Yeah, that's right.
They also have a unique object ID.
If we look at our greeting object, if we look at the object ID for that, and then we look
at the farewell objects ID, they're two separate objects in memory.
And just to drive this home, let's try just one more example.
Let's say we have a time object.
I'll call it t1.
We use time.new to get that object.
So that's got the current time when I type that in.
It has methods like what is the current second or is it Monday, for example.
But we haven't yet created a t2 object, Mike.
Oh, that's supposed to be the t1 object, actually.
t1, it's not Monday, either way we do it.
All right, so we've got a t1 object.
Let's try another time object.
t2, we can ask it.
It's got a unique state.
That's a slightly different time.
It's off by a couple seconds.
But we call methods on it like seconds.
And we can also call Monday.
I'll do that on the right object this time.
Right.
And it's false.
So we've got t1 and t2 both have unique state, the current or the time at which they were
created.
But they've got a same set of behaviors.
Now this is really important.
So let's return to the diagrams with these examples.
A class is a template or blueprint for creating objects.
We instantiate objects from the class.
Each object has common behavior, but different values for its state.
So here we create a string object with the characters hello.
All Ruby strings have common behavior, including reverse, upcase, and so on.
We can also create a string object with the characters goodbye.
Again, they're sharing the same behavior as all strings.
And Mike showed us the same thing with the time class.
Each time object stores its own internal time when it is created and shares the time related
methods.
So the takeaway is we create objects, sometimes called instances, from a class.
And an object is some state variables and behavior, a set of methods.
So you can think of it this way.
State plus behavior equals object.
So how do you know when to create a class?
Well, when designing object-ornied programs, you try to identify the things that your program
is going to deal with.
And then you can define classes to then create those objects.
Let's return to our movie example.
So our code currently looks something like this.
We have three different movie listings, and we've got different names and ranks for each
movie.
It seems fairly obvious that we need something to represent the concept of a movie in our
program.
So we'll need some movie objects.
So it follows that we also need to create a movie class.
That's right.
We want to create a movie class that will create movie objects with the title and rank
and some shared methods.
So it will look like this.
We'll get a movie object for Goonies with the rank of 10 and a movie object for Ghostbusters
with the rank of 9, and they'll share some methods.
So Mike, let's create a movie class.
Sure.
Let's just go ahead and clear out this file.
And we're going to start fresh here.
We want a movie class.
So I'm going to start.
We start with the keyword class, and then we want the name of the class.
In this case, it's a movie.
And class names always begin with an uppercase letter.
And then we just use the keyword end.
So that's the entire definition for a movie class, or at least the beginning of one.
Now let's create some objects from that class.
So let's say we have movie1.
We can just call movie.new.
And let's just go ahead and print out its object ID here.
So when we run this, we've got the object ID for an object.
So we just got an object in memory, a movie object in memory somewhere.
So let's create another one now.
We've got a class.
We can create multiple objects.
So we'll create another movie object, and we'll actually print out its object ID as
well.
I forgot to put a put us in front of there.
If we run that, sure enough, we've got two movie objects.
OK, so we know we've got two objects with two distinct IDs.
Now we actually want to pass in some variables to these.
We want to initialize some state of this movie.
We know that a movie has a title.
So when I create the movie, I want to pass in the title.
In this case, it will be called Goonies.
And we want to also pass in a rank like that.
And then this movie will be something like Ghostbusters, and its rank will be 9.
So if we run this now, we get this error, wrong number of arguments, 2 for 0.
An interesting part of this is notice that new is being called, but this method initializes
also being called on line 4.
If we look at line 4, we're not calling initialize somewhere.
So what's going on here?
Well what happens is when you call new on a class, it kind of just sets up some initial
memory for that object, but it doesn't initialize any of its state.
Ruby doesn't know how to do that.
Instead, new call turns around, and it calls a method called initialize, and it's going
to pass in those parameters to initialize.
So inside of our movie class, we need to define the method called initialize.
It's going to take two parameters, our title and our rank, just like that.
And inside of initialize, I'll just print out created a movie object with title, title,
and rank, rank, just like that.
Save it off.
Now if we run it, we see that that string is being printed.
So the initialize method is being called, and we see that our parameters are getting
passed in.
We've got Goonies and a rank of 10.
OK, this is cool.
So now we have our two movie objects, but they can't really do much yet.
Right, so let's add some behavior.
I only need one movie object for right now.
I'm just going to take that one away.
So let's say we want to do something like this.
We want to call putS, and then we're going to take our movie one object, and let's say
we want to call a method called listing that's going to return a string, and then we can
print it out to the console.
Now notice here that we want to call listing on this particular object.
So we have a receiver here.
This is often called an instance method.
We want to call that method on an instance of the movie class.
So let's go ahead and define that method up in our class.
We'll just define listing like that.
And inside the listing, I want to return a string, and I want the string to be title
has a rank of rank, just like that.
Let's go ahead and run it.
Oh.
Yeah, we get our initial string when we created the movie object up in the initialize method,
but then we get this undefined local variable or method title, which is on line seven.
So what's going on here?
Well, inside of this method, remember, methods are like little black boxes.
What Ruby's trying to do here is find a local variable called title and a local variable
called rank, but it's not finding those.
Remember when we called initialize, these parameters were passed in.
Title and rank up here were set to whatever we passed in, but then when the initialize
method ends, those variables then evaporate.
So we need some way to hold onto these variables inside of initialize so then we can reference
them later inside of listing.
And the way we do that is to transfer these variables over to what's called an instance
variable.
And an instance variable begins with an at sign, and I'm going to call the first one
title, although it doesn't have to match the incoming parameter, and I'm going to assign
to that the local variable title.
In the same way, I'm going to have an instance variable called rank, and I'm going to transfer
over the value of the rank parameter that's coming in.
And while I'm at it, I'll go ahead and call capitalize on this title, capitalize on the
title there so that the title instance variable always has the capitalized form of the title
there.
So what's cool about instance variables here is they live for the life of the object, and
instance methods can then access those instance variables.
So down in listing now, we can change this to at title, that's the name of the instance
variable, and we can change this to at rank.
Now when we run the program, it works as we would expect.
Goonies has a rank of 10.
And just to clean this up a little bit more, we can actually remove this put s line because
we know that this is getting initialized the way we want.
All the instance variables are set.
So our state of our object is getting set up and initialized for us, and then our instance
methods can turn around and use that state.
Now we should probably point out that the instance variable name does not need to match
the parameter name.
That's a really good point.
These are two separate variables.
At rank is an instance variable, rank is a local variable.
So we could call this, for example, the rank if we wanted to.
And then we just have to make sure that wherever we reference that, we'd have to change it
to the rank.
Let's go ahead and add in another movie here.
I took it away earlier, but we want a couple movies in here.
So movie two is going to be.
Ghostbusters.
Ghostbusters back.
Ghostbusters, and we'll have a rank of nine.
And then we can call the method movie two dot listing because it's an instance method
on the object.
And now we've got two movies.
Now remember that methods can take a default parameter value.
So we could actually change our rank to have a default of zero.
Yeah, let's do that with a third movie.
Let's say we have movie three.
It's going to be.
Goldfinger.
Goldfinger.
And we don't want to pass in an initial rank here.
So this isn't going to work if we run it because it's a required parameter.
But we know that initialize is just like any other method.
It can take default parameter value.
So we'll just change that to a zero just like that.
And I suppose I should print out Goldfinger's listing at the bottom.
And there we go.
Three movies.
So we need a way to print out multiple movies.
We're going to do that over and over and over.
Yeah.
It's kind of inconvenient if we always have to call this listing method to print out movies.
So what we'd rather do is instead of calling listing here, we'd rather just pass the entire
movie object into the put s method.
Right.
So just put s movie one.
What could be simpler than that?
Right.
So if we run this now, we actually get this kind of not very convenient output.
We just get the name of the class movie and then some hex value here.
So what's happening is when you pass an object to put s, put s is going to try to convert
that object into its string representation.
And the way it does that is to call this method called to underscore s on an object.
And all objects have these.
It just happens to be that the default implementation of that method isn't very helpful.
So we can change that.
We've got this listing up here.
It returns a string.
To s is expected to return a string.
So we can just change this to to underscore s.
This method will get automatically called when put s tries to convert this object over
to a string.
So let's go ahead and run that.
And now we get the string that we expect when we print out the entire movie object.
All right.
So this is pretty cool because we can now create movie objects.
And then when we talk to each movie, we can just use one variable.
We can use movie one refers to the whole object, movie two, and movie three.
We also have a place where we can now add behavior.
Like we could thumbs up a movie or thumbs down a movie.
Yeah.
When we thumbs up a movie, we just increase its rank by one.
And if we thumbs down a movie, we decrease its rank by one.
Right.
So we need some way to change the internal state of a movie.
It's at rank instance variable.
That kind of reminds me of an old programming maxim called tell don't ask.
So rather than ask an object for its state, then make some decision on its behalf and
then tell the object what to do.
We prefer to tell the object what to do straight away and then let it figure out how to do
that.
And we tell an object to do something by calling a method.
So we need to write two methods.
We need a thumbs up and a thumbs down.
Yeah.
Let's start with the thumbs up method.
So we want to be able to thumbs up a particular object.
So we're going to need an instance method to help us do that.
So I'm just going to define an instance method up here.
I'm going to call it thumbs up, just like that.
And all this method is going to do is we want to assign a new rank and it's going to be
the existing rank plus one.
So we're just going to add one to the rank and then down for Goonies, for example, and
call movie one dot thumbs up.
It's going to start at a rank of 10.
That's its initial rank.
Now, if we run it, it now has a rank of 11.
So now we need a way to thumbs down in movie objects.
We need another instance method for that.
We're going to define thumbs down.
The implementation of that will be to take the existing rank and subtract one.
And then let's see.
Yeah, let's thumbs down Ghostbusters.
You know, that was kind of scary in its day.
Thumbs down to Ghostbusters.
We're so sorry.
Right.
So it starts at nine and if we run it, now it has a rank of eight.
So now the object has state and behavior.
Right, right.
We can thumbs up or thumbs down it and change the internal state, the rank.
One little thing I'd like to do here, though, is we saw when we're thumbs up and we just
take the initial rank and add one.
There's a shortcut we can use in Ruby to do this.
And it's just this plus equals.
Plus equals is going to take the existing value of rank, add one, and then assign it
back to the rank instance variable.
In the same way for thumbs down, we can do minus equals and that'll subtract one from
the existing value.
And we get exactly the same thing.
Okay, so here's a slow motion replay.
When we call the new method like this, we get a new movie object with its instance variables
already filled in.
Goonies and a rank of 10.
Then to change the movie state, we call methods.
So by calling thumbs down, the rank changes from 10 to nine.
Calling it again changes the rank from nine to eight.
And here's another movie object with different values for its instance variables.
We call thumbs up on it and it changes the rank from nine to 10.
And then we call it again and it changes the rank from 10 to 11.
So now we have two objects with two distinct states.
We can think of each object like another black box.
From the outside, you interface with it by calling methods and you don't actually know
what goes on inside.
This is the beauty of objects.
So just a quick vocab review here.
We set up our state in the initialized method by setting instance variables.
And then our behavior is expressed as instance methods inside of the class.
Then we use the class to create an object and then we can call those instance methods
on the object.
All right, so you're ready to give this a go for yourself?
In the exercise, you're going to write your own player class.
You're also going to write some methods to change up the state of your players, very
similar to how we change the state of our movies.
And now that we have a start on classes, in the next section, we'll look at another aspect
of classes called attributes.
We'll see you then.
See you then.
Can't find what you're looking for?
Get subtitles in any language from opensubtitles.com, and translate them here.