All language subtitles for pragstudio-ruby-21-mixins (Transcribed on 24-Apr-2023 20-59-40)

af Afrikaans
ak Akan
sq Albanian
am Amharic
ar Arabic
hy Armenian
az Azerbaijani
eu Basque
be Belarusian
bem Bemba
bn Bengali
bh Bihari
bs Bosnian
br Breton
bg Bulgarian
km Cambodian
ca Catalan
ceb Cebuano
chr Cherokee
ny Chichewa
zh-CN Chinese (Simplified) Download
zh-TW Chinese (Traditional)
co Corsican
hr Croatian
cs Czech
da Danish
nl Dutch
en English
eo Esperanto
et Estonian
ee Ewe
fo Faroese
tl Filipino
fi Finnish
fr French
fy Frisian
gaa Ga
gl Galician
ka Georgian
de German
el Greek
gn Guarani
gu Gujarati
ht Haitian Creole
ha Hausa
haw Hawaiian
iw Hebrew
hi Hindi
hmn Hmong
hu Hungarian
is Icelandic
ig Igbo
id Indonesian
ia Interlingua
ga Irish
it Italian
ja Japanese
jw Javanese
kn Kannada
kk Kazakh
rw Kinyarwanda
rn Kirundi
kg Kongo
ko Korean
kri Krio (Sierra Leone)
ku Kurdish
ckb Kurdish (Soranî)
ky Kyrgyz
lo Laothian
la Latin
lv Latvian
ln Lingala
lt Lithuanian
loz Lozi
lg Luganda
ach Luo
lb Luxembourgish
mk Macedonian
mg Malagasy
ms Malay
ml Malayalam
mt Maltese
mi Maori
mr Marathi
mfe Mauritian Creole
mo Moldavian
mn Mongolian
my Myanmar (Burmese)
sr-ME Montenegrin
ne Nepali
pcm Nigerian Pidgin
nso Northern Sotho
no Norwegian
nn Norwegian (Nynorsk)
oc Occitan
or Oriya
om Oromo
ps Pashto
fa Persian
pl Polish
pt-BR Portuguese (Brazil)
pt Portuguese (Portugal)
pa Punjabi
qu Quechua
ro Romanian
rm Romansh
nyn Runyakitara
ru Russian
sm Samoan
gd Scots Gaelic
sr Serbian
sh Serbo-Croatian
st Sesotho
tn Setswana
crs Seychellois Creole
sn Shona
sd Sindhi
si Sinhalese
sk Slovak
sl Slovenian
so Somali
es Spanish
es-419 Spanish (Latin American)
su Sundanese
sw Swahili
sv Swedish
tg Tajik
ta Tamil
tt Tatar
te Telugu
th Thai
ti Tigrinya
to Tonga
lua Tshiluba
tum Tumbuka
tr Turkish
tk Turkmen
tw Twi
ug Uighur
uk Ukrainian
ur Urdu
uz Uzbek
vi Vietnamese
cy Welsh
wo Wolof
xh Xhosa
yi Yiddish
yo Yoruba
zu Zulu

Original subtitles

Now in the last section we looked at how inheritance can be used to share code that's common between

classes. And this works well with classes that have a natural inheritance relationship.

For example, your clumsy player is a kind of player and our 3D movie is a kind of movie.

Right, but sometimes we have code that we want to share across classes that don't have

an is a relationship. And Ruby has a wonderful alternative to inheritance called mixins.

A mixin is simply a module that has methods and those methods get mixed into other classes.

So for example, imagine a scenario where we want to model the concept of a song. We would

create a song class. And a song should be rankable, just like a movie. We can thumbs

up it or thumbs down it. And currently all that behavior lies in the movie class.

But we don't want to copy all that behavior into the song class. We'd end up with duplication.

And it doesn't make sense for a song to inherit from a movie. It doesn't pass the is a rule.

A song is not a kind of movie.

Instead we want to put all the rank related code in a module.

So let's say we have these two classes, a movie class and a song class. And suppose

we want to share some common behavior across these classes which aren't in the same inheritance

hierarchy. For example, to keep it simple, suppose we want to be able to call a thumbs

up method and print out their name. Well, we could write a thumbs up method inside of

each of these classes, but then we'd end up with duplication. So instead we can write

a module. We'll call the module rankable, like that. And then inside of the module we'll

define that thumbs up method.

Inside of the thumbs up method, all we're going to do for now, just to keep it simple,

is we're going to print out the title, Got a Thumbs Up. Just like that.

Now a couple things to note here. This is a regular instance method. Remember when we

defined methods before in modules, we would put self dot and then we would call it on

the module. Well in this case, we're defining an instance method, thumbs up.

Now we saw before that we can't create an instance of the rankable module. Therefore

we can't call this instance method directly. The way that we call it is we mix it into

these classes below. So down in movie, to mix in this module rankable, I say include

rankable and then down in song, I would do the same thing, include rankable like that.

Now inside of movie, or for a movie object, I can call it movie dot thumbs up and in the

same way I can take a song and call thumbs up on it. If we run that, sure enough, Goonies

got a thumbs up and Ruby Baby got a thumbs up. So they both have a thumbs up method that

came from this module. Something else to notice is the module or the instance method here,

we can use at title because the point at which this method gets run will be when it's down

inside of a movie and a movie has a title instance variable and so does a song.

So something kind of cool about this is mixed in modules effectively behave like super classes.

In other words, it changes the method lookup hierarchy. The module lives between the classes

that include the module and their direct super class. So when we call a method, it looks

in the class, then it looks in the module, then it looks in the super class and then

all the way to the top. We can look at this another way by loading up our mixins file

where we've got our song on our movie there and it printed out some code that we have,

some example code. But if we look at movies.movie.ancestors now, we've got movie, but then notice that

the module name rankable is between movie and the object. So Ruby is going to look here

for methods, then at rankable, then up to object. So it's inserted the module into the

lookup hierarchy here. In the same way, if we look at songs ancestors, rankable is between

it and object. And something kind of interesting, if we look at something like arrays ancestors,

we have the array class, but we have this module in here called enumerable. And that's

where all those methods like select, reject, and partition live. They get mixed into the

array class. In the same way, if we look at hashes ancestors, we have hash and it also

includes the enumerable module. So that's why array and hash both have methods like

each and select and reject and all those common methods. It's because they pick up those methods

from the same enumerable module.

So now that we understand how mixins work, let's return to our movie.

Yeah, and in the movie app, we'll create a similar rankable module that we just did

in this little example file. And then we'll mix it into both movie and I'll create a class

called song just to see that we can mix it in there too.

Perfect.

So back over in our movie class, we have these two methods, thumbs up and thumbs down, which

really has to do with ranking things. So let's extract these out into a module. I'm just

going to cut them out of our movie class here. And I'm going to create a new file. I'm going

to call that file rankable.rb. And then we'll create a module inside that file. We'll call

the module rankable. We'll put in those two methods. So anything that's rankable is going

to have the behavior of being able to thumbs up or get thumbs down. And the module just

assumes that when we mix these methods into a class, that that class has an at rank instance

variable, which our movie does. So back over to our movie now at the top, we need to make

sure we require our new rankable module. And then to mix those methods into our movie class,

we need to include rankable just like that.

Now if we go out over the command line and run our program again, we can run Ruby flix.rb

and we'll just say we want three viewings. And sure enough, things are getting thumbs

up and thumbs down just like we would expect. So we've just moved that code into our rankable

module and then mixed it in.

So let's take this a step further. If we go back over to movie, what other parts of movie

have to do with being ranked? Well, let's see. We've got this hit method and this status

method. They go together and they act on the at rank instance variable. We could also put

our normalized rank in there. And in fact, we could even put in the overloading of this

comparison operator because that has to do with rank as well. So let's just cut this

out of here. We'll go to our rankable module again. And we've got that. So the module can

thumbs up, thumbs down, determine hits and statuses, and also do sorting based on the

rank of things.

And just to make this a little bit more generic, I might change this to just other instead

of other movie because it doesn't really matter. It's anything that has a rank attribute and

a rank instance variable. So we've totally encapsulated the idea of something being rankable.

Just to make sure, I'm going to go back over to the command line. Let's run our program

one more time. Let's say we want 10 viewings. And sure enough, we're getting what we expect.

So the program still works from the outside exactly as it did before. We've just encapsulated

the notion of something being rankable.

Okay, so that works, but it's generally considered better practice if a module depends on a method

or an attribute in the hosting class, the class that it gets mixed into, as opposed

to relying on the instance variable being present. So let's change that around. We'll

just go back to rankable here. And instead of relying on this rank instance variable,

let's just assume that the class it gets mixed into has an attribute called rank. So we could

just call self.rank. That's going to be the object that we get mixed into. And we're using

the attribute there for rank. And we'll change this one to self as well.

So get rid of all the instance variable references to rank. And the same thing right down here.

So these ones where we're just accessing rank, self.rank, we're using the reader attribute

to do that. But up here where we're thumbs-upping and thumbs-downing, we're actually changing

the rank. And if we look over in our movie, our rank is still a read-only attribute. We

have attribute reader here.

So to make this work, we're going to change this to an accessor. And now we've got a reader

and a writer for rank, which means that rankable is now just dependent on any class that it

gets mixed into just has to have an accessor called rank. And that means we have a fairly

clean separation of concerns here. The rankable module just deals with rankable things. And

it doesn't care what instance variables are available in the hosting class.

So mix-ins are less coupled than inheritance. They're not an is a relationship. We can just

put code inside of modules and then mix them in wherever we want to. And we can mix in

more than one module as well. So a song might be rankable, searchable, and even danceable.

And a movie is just rankable and searchable. We can mix and match these things as we go.

And this is a preferred design in Ruby.

So when designing your software, try to identify able behaviors and encapsulate those behaviors

into modules that then you can mix into multiple classes.

So now we've looked at two design techniques for sharing common code, inheritance and mix-ins.

In the exercise, you're going to put a couple mix-ins in the game.

And when you're done, we'll have all the features of the game implemented. So in the

next section, we'll look at how to package up our code as a Ruby gem so we can distribute

it out to your friends or the rest of the world.

So come on back.

Can't find what you're looking for?
Get subtitles in any language from opensubtitles.com, and translate them here.