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
Now, the objects we've created so far have an internal state.
Your player objects have a name and a health, and our movie objects have a title and a rank,
and our instance methods have access to that state.
Yeah, but say we wanted to access that state from outside of the class.
For example, we might want to access the title or the rank from outside of the movie class.
So we could just try printing out the movie's title by calling movie1.title here.
If we run that, ooh, we get this error, undefined method title for Goonies.
So what's happening here is it's trying to call a method called title, and we don't have
one of those defined.
So by default, an object state is private.
We can't get access to it.
In general, this is a really good thing.
It means that the object is solely responsible for maintaining its own consistency.
In other words, it encapsulates its details.
We don't get access to the instance variables from the outside by default.
But you'll normally want to define methods that let you access and manipulate the state
of an object, allowing the outside world to interact with that object.
And in this case, we can do that simply by following the error message and defining a
title method.
So we'll just write this as an instance method inside of the class.
We'll call it title.
And all we need this method to do is return the value of the title instance variable.
And if we do that and we run it, now we've provided access to that movie title.
We see Goonies right here.
But that's so common to have to write a method like this.
We sometimes call these getter methods that Ruby provides a shortcut.
And the shortcut is to use a little kind of like macro level syntax.
It feels like it's a method called ATTR reader.
And then we give ATTR reader the name of the method or the name of the instance variable
for which we want a reader method to be generated.
So I'm going to do that using a symbol.
I'm going to say I want a method named title.
Now don't worry too much about symbols right now.
They're just these things that start with a colon.
You can think of them as a simple string.
We'll talk more about symbols later.
But all this is saying is make me a method called title.
And by convention, it will return the value of the title instance variable.
So writing this line of code is just like writing that line of code or these three lines
of code I should say.
So we can actually get rid of that.
If we run it now, sure enough, we still have our title being printed.
We could also do that for rank.
We could.
Yeah.
If we want to print out the rank, movie1.rank for example, then all we need to do is create
a reader for that rank.
And we could do this on a separate line or we can just use commas to separate multiple
readers.
So that's going to write us a method called rank that returns the value of the rank instance
variable.
And sure enough, we've got the title and the rank now.
So now let's say we actually wanted to change the title of a movie.
How would we do that?
Well, it might look something like this.
We want to take, I'm just going to give a little bit more space here.
We're going to take our movie1 object and we would call title and we want to assign
to that a new title.
Maybe it's Goonies spelled a little bit differently with an exclamation point at the end.
Goonies 2.0.
That's the 2.0 version of Goonies.
You're right.
All right.
So I'm going to print out the movie title again just to see that it changed.
Well, let's just try to run that and we get an error.
It says undefined method titled equals.
Notice that the method name here is titled with an equal sign at the end for Goonies.
So the error pretty much gives us a clue as to what we need to do here.
We come back up into our class.
We're going to define a method.
The method is going to be called titled equals, just like the error method said we should
have.
It's going to take a parameter.
This is the new title that we want and then inside of that method, we'll just take our
title instance variable and we'll assign to it the new title, just like that.
We run this now.
Sure enough, we started with Goonies and then we printed out again.
We've got our Goonies 2.0 being printed.
Now again, it's so common to want to have these writer methods like this or setter methods
that Ruby provides a shortcut and the shortcut for this is attr writer and then we give it
the name of the instance variable that we want or the attribute that we want called
title and that line of code when it runs as this class is being defined, it's going to
run that line of code and it's going to generate a method on the fly that looks pretty much
exactly like this.
So it just follows the conventions to do that.
So we can get rid of this and everything still runs.
Now in this case, title is both readable and writable and we have that specified in two
separate attribute lines here.
But we can combine it into one by using attr accessor, that's the shortcut, and just do
title, and attr accessor is going to create both methods for us, the getter and the setter.
And then we can just change this one.
We just want the rank to be readable right now because rank is just something you read.
You change the rank by calling thumbs up or thumbs down.
So we've got our two attributes.
We've got our rank attribute and we've got a title attribute.
Now you'll normally see these attribute lines at the top of the class.
So I'm just going to go ahead and move those up.
You'll normally see them right here because you can look at the class definition, you
see what attributes the class has, and then you see how the initialize sets up those attributes.
So I'm just going to leave those there for now.
All right, so let's recap.
Using attr reader is the same as writing this method.
It's sometimes called a getter method and that returns the value of the instance variable.
And using attr writer is the same as writing this method, sometimes called a setter method,
and that sets the value of the instance variable.
Like Mike said, you often want to read and write an instance variable, so attr accessor
is the same as writing both of these methods.
Which might leave you wondering, why not just use attr accessor all the time for everything?
Well, remember that an object is responsible for managing its own internal state.
And when you use an attribute, you're potentially exposing that state to the outside world.
So what you choose to expose is very much a design decision.
If you just need the outside world to be able to read some attribute, make it attr reader.
If they're going to be able to read and write an attribute, make it attr accessible.
And if an attribute is just used for internal methods, you don't want to expose it to the
outside world, then don't make an attribute at all.
Now, generally speaking, all your attributes will map to instance variables.
However, we can create something called a virtual attribute.
So let's say we wanted to access the rank as a normalized value, say between 1 and 10.
That's actually a great example of a virtual attribute, because we don't have an instance
variable for that.
So our initial inclination here might be to actually create an instance variable called
normalized rank inside of our initialized method.
And then we could just set it to, you know, at rank divided by 100 or 10 or whatever we
want to normalize it to.
But we actually don't have to do that.
Instead, we can just write a method, we'll call the method normalized rank.
And then when that method is called, we'll just go ahead and derive the value.
So it'll be the rank divided by 10, for example.
Then down, if we want to use that, we'll just say put as movie1.normalizedRank.
Well it got normalized to 1.
Oh, poor Goonies got sent to the bottom of the stack.
They did.
I'll just boost its rank all the way up to 100.
I'm going to take off some of this stuff at the bottom, run it now, and 100 gets normalized
to 10.
All right.
So from the outside world, this looks like a regular attribute.
There's no idea that this is actually some derived value.
And that's what a virtual attribute is all about.
It's just a method that derives from existing instance variables.
So what if we wanted to use this normalized rank method from inside of this class?
For example, down in our 2S method, instead of using at rank here, what if we wanted to
use the normalized rank?
Well, we can just change that to normalized rank.
There's no at sign here.
Remember, this is a method call.
We run it and we get 10 again.
It's kind of interesting.
We've got a method 2S.
It's turnaround and calling the normalized rank method.
Both of these are instance methods inside of the class, so 2S can call normalized rank.
And just coming back to self just a little bit here, we might be wondering, well, what's
the receiver on this normalized rank method?
Well, the way Ruby figures this out is first it looks for a local variable called normalized
rank inside of this method.
It doesn't find one.
So then it sees that there's not an explicit receiver.
It's going to use the implicit receiver, which we already know is this self variable, right?
And then it just calls that method on that object.
So question here is, what is the value of self inside of this instance method?
Well, what happens, and we talked about self changing throughout the program, when we call
normalized rank down here, it's being called on the movie one object.
When this method is called, self is automatically changed to be that object movie one.
So it's as if we typed movie one dot normalized rank, but that wouldn't be very generic.
That wouldn't work for all of our movie objects.
So instead, self is automatically set to whatever object or receiver we're calling the method
on.
So we know that self will be used implicitly, so we don't have to type self dot there.
Okay, you guessed it.
It's exercise time.
Now this is a fairly simple, but it's a really important exercise and it's going to give
you some practice with attributes.
Now once you've created a bunch of objects, it's fairly common to want to put them in
a collection of some sort.
So we'll look at that next.
Oh yeah, that's my favorite section.
Here come the arrays.
Can't find what you're looking for?
Get subtitles in any language from opensubtitles.com, and translate them here.