Would you like to inspect the original subtitles? These are the user uploaded subtitles that are being translated:
1
00:00:00,000 --> 00:00:08,260
Now, the objects we've created so far have an internal state.
2
00:00:08,260 --> 00:00:13,500
Your player objects have a name and a health, and our movie objects have a title and a rank,
3
00:00:13,500 --> 00:00:16,420
and our instance methods have access to that state.
4
00:00:16,420 --> 00:00:20,560
Yeah, but say we wanted to access that state from outside of the class.
5
00:00:20,560 --> 00:00:25,300
For example, we might want to access the title or the rank from outside of the movie class.
6
00:00:25,300 --> 00:00:31,080
So we could just try printing out the movie's title by calling movie1.title here.
7
00:00:31,080 --> 00:00:36,120
If we run that, ooh, we get this error, undefined method title for Goonies.
8
00:00:36,120 --> 00:00:40,820
So what's happening here is it's trying to call a method called title, and we don't have
9
00:00:40,820 --> 00:00:42,380
one of those defined.
10
00:00:42,380 --> 00:00:45,200
So by default, an object state is private.
11
00:00:45,200 --> 00:00:46,940
We can't get access to it.
12
00:00:46,940 --> 00:00:48,480
In general, this is a really good thing.
13
00:00:48,480 --> 00:00:53,580
It means that the object is solely responsible for maintaining its own consistency.
14
00:00:53,580 --> 00:00:55,720
In other words, it encapsulates its details.
15
00:00:55,720 --> 00:00:59,940
We don't get access to the instance variables from the outside by default.
16
00:00:59,940 --> 00:01:04,120
But you'll normally want to define methods that let you access and manipulate the state
17
00:01:04,120 --> 00:01:07,480
of an object, allowing the outside world to interact with that object.
18
00:01:07,480 --> 00:01:11,960
And in this case, we can do that simply by following the error message and defining a
19
00:01:11,960 --> 00:01:13,440
title method.
20
00:01:13,440 --> 00:01:17,000
So we'll just write this as an instance method inside of the class.
21
00:01:17,000 --> 00:01:18,160
We'll call it title.
22
00:01:18,160 --> 00:01:23,440
And all we need this method to do is return the value of the title instance variable.
23
00:01:23,440 --> 00:01:28,160
And if we do that and we run it, now we've provided access to that movie title.
24
00:01:28,160 --> 00:01:30,039
We see Goonies right here.
25
00:01:30,039 --> 00:01:32,759
But that's so common to have to write a method like this.
26
00:01:32,759 --> 00:01:36,860
We sometimes call these getter methods that Ruby provides a shortcut.
27
00:01:36,860 --> 00:01:40,840
And the shortcut is to use a little kind of like macro level syntax.
28
00:01:40,840 --> 00:01:44,860
It feels like it's a method called ATTR reader.
29
00:01:44,860 --> 00:01:51,560
And then we give ATTR reader the name of the method or the name of the instance variable
30
00:01:51,560 --> 00:01:53,920
for which we want a reader method to be generated.
31
00:01:53,920 --> 00:01:56,040
So I'm going to do that using a symbol.
32
00:01:56,040 --> 00:01:58,640
I'm going to say I want a method named title.
33
00:01:58,640 --> 00:02:01,000
Now don't worry too much about symbols right now.
34
00:02:01,000 --> 00:02:02,720
They're just these things that start with a colon.
35
00:02:02,720 --> 00:02:04,800
You can think of them as a simple string.
36
00:02:04,800 --> 00:02:06,720
We'll talk more about symbols later.
37
00:02:06,720 --> 00:02:11,320
But all this is saying is make me a method called title.
38
00:02:11,320 --> 00:02:16,800
And by convention, it will return the value of the title instance variable.
39
00:02:16,800 --> 00:02:21,420
So writing this line of code is just like writing that line of code or these three lines
40
00:02:21,420 --> 00:02:22,559
of code I should say.
41
00:02:22,559 --> 00:02:24,920
So we can actually get rid of that.
42
00:02:24,920 --> 00:02:28,640
If we run it now, sure enough, we still have our title being printed.
43
00:02:28,640 --> 00:02:30,320
We could also do that for rank.
44
00:02:30,320 --> 00:02:31,320
We could.
45
00:02:31,320 --> 00:02:32,320
Yeah.
46
00:02:32,320 --> 00:02:37,640
If we want to print out the rank, movie1.rank for example, then all we need to do is create
47
00:02:37,640 --> 00:02:39,859
a reader for that rank.
48
00:02:39,859 --> 00:02:43,839
And we could do this on a separate line or we can just use commas to separate multiple
49
00:02:43,839 --> 00:02:44,839
readers.
50
00:02:44,839 --> 00:02:48,760
So that's going to write us a method called rank that returns the value of the rank instance
51
00:02:48,760 --> 00:02:49,760
variable.
52
00:02:49,760 --> 00:02:52,600
And sure enough, we've got the title and the rank now.
53
00:02:52,600 --> 00:02:56,040
So now let's say we actually wanted to change the title of a movie.
54
00:02:56,040 --> 00:02:57,040
How would we do that?
55
00:02:57,040 --> 00:02:58,840
Well, it might look something like this.
56
00:02:58,840 --> 00:03:01,399
We want to take, I'm just going to give a little bit more space here.
57
00:03:01,399 --> 00:03:05,579
We're going to take our movie1 object and we would call title and we want to assign
58
00:03:05,579 --> 00:03:07,200
to that a new title.
59
00:03:07,200 --> 00:03:11,519
Maybe it's Goonies spelled a little bit differently with an exclamation point at the end.
60
00:03:11,519 --> 00:03:12,940
Goonies 2.0.
61
00:03:12,940 --> 00:03:14,760
That's the 2.0 version of Goonies.
62
00:03:14,760 --> 00:03:15,760
You're right.
63
00:03:15,760 --> 00:03:16,760
All right.
64
00:03:16,760 --> 00:03:20,040
So I'm going to print out the movie title again just to see that it changed.
65
00:03:20,040 --> 00:03:22,760
Well, let's just try to run that and we get an error.
66
00:03:22,760 --> 00:03:26,560
It says undefined method titled equals.
67
00:03:26,560 --> 00:03:30,920
Notice that the method name here is titled with an equal sign at the end for Goonies.
68
00:03:30,920 --> 00:03:33,899
So the error pretty much gives us a clue as to what we need to do here.
69
00:03:33,899 --> 00:03:35,180
We come back up into our class.
70
00:03:35,180 --> 00:03:36,980
We're going to define a method.
71
00:03:36,980 --> 00:03:41,040
The method is going to be called titled equals, just like the error method said we should
72
00:03:41,040 --> 00:03:42,040
have.
73
00:03:42,040 --> 00:03:43,040
It's going to take a parameter.
74
00:03:43,040 --> 00:03:47,440
This is the new title that we want and then inside of that method, we'll just take our
75
00:03:47,440 --> 00:03:52,320
title instance variable and we'll assign to it the new title, just like that.
76
00:03:52,320 --> 00:03:53,880
We run this now.
77
00:03:53,880 --> 00:03:56,320
Sure enough, we started with Goonies and then we printed out again.
78
00:03:56,320 --> 00:03:59,200
We've got our Goonies 2.0 being printed.
79
00:03:59,200 --> 00:04:04,320
Now again, it's so common to want to have these writer methods like this or setter methods
80
00:04:04,320 --> 00:04:10,359
that Ruby provides a shortcut and the shortcut for this is attr writer and then we give it
81
00:04:10,360 --> 00:04:14,240
the name of the instance variable that we want or the attribute that we want called
82
00:04:14,240 --> 00:04:18,960
title and that line of code when it runs as this class is being defined, it's going to
83
00:04:18,960 --> 00:04:23,120
run that line of code and it's going to generate a method on the fly that looks pretty much
84
00:04:23,120 --> 00:04:24,840
exactly like this.
85
00:04:24,840 --> 00:04:27,160
So it just follows the conventions to do that.
86
00:04:27,160 --> 00:04:30,880
So we can get rid of this and everything still runs.
87
00:04:30,880 --> 00:04:35,280
Now in this case, title is both readable and writable and we have that specified in two
88
00:04:35,280 --> 00:04:37,560
separate attribute lines here.
89
00:04:37,560 --> 00:04:43,680
But we can combine it into one by using attr accessor, that's the shortcut, and just do
90
00:04:43,680 --> 00:04:48,120
title, and attr accessor is going to create both methods for us, the getter and the setter.
91
00:04:48,120 --> 00:04:49,960
And then we can just change this one.
92
00:04:49,960 --> 00:04:54,480
We just want the rank to be readable right now because rank is just something you read.
93
00:04:54,480 --> 00:04:57,440
You change the rank by calling thumbs up or thumbs down.
94
00:04:57,440 --> 00:04:58,880
So we've got our two attributes.
95
00:04:58,880 --> 00:05:02,120
We've got our rank attribute and we've got a title attribute.
96
00:05:02,120 --> 00:05:05,480
Now you'll normally see these attribute lines at the top of the class.
97
00:05:05,480 --> 00:05:07,160
So I'm just going to go ahead and move those up.
98
00:05:07,160 --> 00:05:10,920
You'll normally see them right here because you can look at the class definition, you
99
00:05:10,920 --> 00:05:15,960
see what attributes the class has, and then you see how the initialize sets up those attributes.
100
00:05:15,960 --> 00:05:17,680
So I'm just going to leave those there for now.
101
00:05:17,680 --> 00:05:20,140
All right, so let's recap.
102
00:05:20,140 --> 00:05:23,180
Using attr reader is the same as writing this method.
103
00:05:23,180 --> 00:05:28,320
It's sometimes called a getter method and that returns the value of the instance variable.
104
00:05:28,320 --> 00:05:33,560
And using attr writer is the same as writing this method, sometimes called a setter method,
105
00:05:33,560 --> 00:05:36,400
and that sets the value of the instance variable.
106
00:05:36,400 --> 00:05:41,479
Like Mike said, you often want to read and write an instance variable, so attr accessor
107
00:05:41,479 --> 00:05:44,440
is the same as writing both of these methods.
108
00:05:44,440 --> 00:05:49,760
Which might leave you wondering, why not just use attr accessor all the time for everything?
109
00:05:49,760 --> 00:05:54,780
Well, remember that an object is responsible for managing its own internal state.
110
00:05:54,780 --> 00:05:59,520
And when you use an attribute, you're potentially exposing that state to the outside world.
111
00:05:59,520 --> 00:06:03,140
So what you choose to expose is very much a design decision.
112
00:06:03,140 --> 00:06:07,440
If you just need the outside world to be able to read some attribute, make it attr reader.
113
00:06:07,440 --> 00:06:12,479
If they're going to be able to read and write an attribute, make it attr accessible.
114
00:06:12,479 --> 00:06:17,159
And if an attribute is just used for internal methods, you don't want to expose it to the
115
00:06:17,159 --> 00:06:20,200
outside world, then don't make an attribute at all.
116
00:06:20,200 --> 00:06:24,880
Now, generally speaking, all your attributes will map to instance variables.
117
00:06:24,880 --> 00:06:29,080
However, we can create something called a virtual attribute.
118
00:06:29,080 --> 00:06:34,640
So let's say we wanted to access the rank as a normalized value, say between 1 and 10.
119
00:06:34,640 --> 00:06:38,000
That's actually a great example of a virtual attribute, because we don't have an instance
120
00:06:38,000 --> 00:06:39,640
variable for that.
121
00:06:39,640 --> 00:06:43,719
So our initial inclination here might be to actually create an instance variable called
122
00:06:43,719 --> 00:06:46,640
normalized rank inside of our initialized method.
123
00:06:46,640 --> 00:06:51,520
And then we could just set it to, you know, at rank divided by 100 or 10 or whatever we
124
00:06:51,520 --> 00:06:52,979
want to normalize it to.
125
00:06:52,979 --> 00:06:54,840
But we actually don't have to do that.
126
00:06:54,840 --> 00:07:01,200
Instead, we can just write a method, we'll call the method normalized rank.
127
00:07:01,200 --> 00:07:03,960
And then when that method is called, we'll just go ahead and derive the value.
128
00:07:03,960 --> 00:07:08,000
So it'll be the rank divided by 10, for example.
129
00:07:08,000 --> 00:07:15,520
Then down, if we want to use that, we'll just say put as movie1.normalizedRank.
130
00:07:15,520 --> 00:07:17,159
Well it got normalized to 1.
131
00:07:17,159 --> 00:07:20,599
Oh, poor Goonies got sent to the bottom of the stack.
132
00:07:20,599 --> 00:07:21,599
They did.
133
00:07:21,599 --> 00:07:23,280
I'll just boost its rank all the way up to 100.
134
00:07:23,280 --> 00:07:28,799
I'm going to take off some of this stuff at the bottom, run it now, and 100 gets normalized
135
00:07:28,799 --> 00:07:29,799
to 10.
136
00:07:29,799 --> 00:07:30,799
All right.
137
00:07:30,799 --> 00:07:33,359
So from the outside world, this looks like a regular attribute.
138
00:07:33,359 --> 00:07:36,799
There's no idea that this is actually some derived value.
139
00:07:36,799 --> 00:07:38,919
And that's what a virtual attribute is all about.
140
00:07:38,919 --> 00:07:43,059
It's just a method that derives from existing instance variables.
141
00:07:43,059 --> 00:07:46,580
So what if we wanted to use this normalized rank method from inside of this class?
142
00:07:46,580 --> 00:07:51,119
For example, down in our 2S method, instead of using at rank here, what if we wanted to
143
00:07:51,120 --> 00:07:53,480
use the normalized rank?
144
00:07:53,480 --> 00:07:55,960
Well, we can just change that to normalized rank.
145
00:07:55,960 --> 00:07:56,960
There's no at sign here.
146
00:07:56,960 --> 00:07:59,040
Remember, this is a method call.
147
00:07:59,040 --> 00:08:02,040
We run it and we get 10 again.
148
00:08:02,040 --> 00:08:03,040
It's kind of interesting.
149
00:08:03,040 --> 00:08:04,480
We've got a method 2S.
150
00:08:04,480 --> 00:08:07,880
It's turnaround and calling the normalized rank method.
151
00:08:07,880 --> 00:08:13,640
Both of these are instance methods inside of the class, so 2S can call normalized rank.
152
00:08:13,640 --> 00:08:17,200
And just coming back to self just a little bit here, we might be wondering, well, what's
153
00:08:17,200 --> 00:08:20,120
the receiver on this normalized rank method?
154
00:08:20,120 --> 00:08:24,760
Well, the way Ruby figures this out is first it looks for a local variable called normalized
155
00:08:24,760 --> 00:08:26,480
rank inside of this method.
156
00:08:26,480 --> 00:08:27,840
It doesn't find one.
157
00:08:27,840 --> 00:08:30,320
So then it sees that there's not an explicit receiver.
158
00:08:30,320 --> 00:08:36,400
It's going to use the implicit receiver, which we already know is this self variable, right?
159
00:08:36,400 --> 00:08:39,320
And then it just calls that method on that object.
160
00:08:39,320 --> 00:08:44,039
So question here is, what is the value of self inside of this instance method?
161
00:08:44,039 --> 00:08:48,920
Well, what happens, and we talked about self changing throughout the program, when we call
162
00:08:48,920 --> 00:08:53,760
normalized rank down here, it's being called on the movie one object.
163
00:08:53,760 --> 00:08:59,680
When this method is called, self is automatically changed to be that object movie one.
164
00:08:59,680 --> 00:09:04,920
So it's as if we typed movie one dot normalized rank, but that wouldn't be very generic.
165
00:09:04,920 --> 00:09:07,360
That wouldn't work for all of our movie objects.
166
00:09:07,360 --> 00:09:13,439
So instead, self is automatically set to whatever object or receiver we're calling the method
167
00:09:13,439 --> 00:09:14,439
on.
168
00:09:14,440 --> 00:09:19,720
So we know that self will be used implicitly, so we don't have to type self dot there.
169
00:09:19,720 --> 00:09:21,280
Okay, you guessed it.
170
00:09:21,280 --> 00:09:22,280
It's exercise time.
171
00:09:22,280 --> 00:09:26,360
Now this is a fairly simple, but it's a really important exercise and it's going to give
172
00:09:26,360 --> 00:09:28,400
you some practice with attributes.
173
00:09:28,400 --> 00:09:31,720
Now once you've created a bunch of objects, it's fairly common to want to put them in
174
00:09:31,720 --> 00:09:33,200
a collection of some sort.
175
00:09:33,200 --> 00:09:34,200
So we'll look at that next.
176
00:09:34,200 --> 00:09:36,560
Oh yeah, that's my favorite section.
177
00:09:36,560 --> 00:09:44,479
Here come the arrays.
16462
Can't find what you're looking for?
Get subtitles in any language from opensubtitles.com, and translate them here.