-: Hi guys and welcome back.
In this video we're going to learn about class composition.
Composition is a counterpart to inheritance
so you build out classes that use other classes.
You're going to be using inheritance very little in Python,
if I'm honest,
you're going to be using composition much more.
Composition allows your classes to be simpler
and reduces the complexity of your code overall,
so it is recommended that you use that most of the time.
In addition, composition means something different
than inheritance when you're thinking about your classes.
For example, we've got here a bookshelf class
that takes in a quantity when you create it
and then when you print it out it tells you
that it's a bookshelf with x books.
For example, here we're creating a bookshelf with 300 books,
when you print it out,
you can see that it says bookshelf with 300 books.
If you wanted to create a book class now,
some new programme has maybe attempted
to make it inherit from bookshelf.
After all, they are somehow related.
Correct?
Books live in bookshelves so.
And then you would do something like this in it
and then you would say the name of the book.
But now if you want this book to call the superclasses
in each method, you also need the quantity of books.
So this is where this is trying to break down a little bit,
a book object doesn't have a quantity of anything.
So anyway, we are going to continue with that example
because we firmly believe that
a book should inherit from bookshelf.
So you'll put your quantity in here
and then you'll say self.name equal name.
Okay, perfect.
Now, this I'm sure you'll realise makes little sense
because you are passing the quantity to a book.
So when you create a book object,
you're going to have to say Harry Potter
and then you're going to have to say something like 120.
Then if you print book,
you'll get something out that's not all that good.
You get bookshelf with 120 books when you print the book.
So clearly you're going to need an str method here
that prints something completely different.
So for example, book self.name.
Okay, let's press play again
and now you get book Harry Potter.
So why is this a bad approach?
Well, there are two reasons.
One of them is conceptual, the way of thinking about it.
The other one is technical.
The conceptual reason is that when you do inheritance,
you are essentially treating it
like evolutionary inheritance.
You're saying that a book is a bookshelf and something more.
For example, in the same way that all tigers are mammals,
but not all mammals are tigers.
So all books are bookshelves,
but not all bookshelves are books.
The bookshelf can still be used on its own.
That breaks down when you talk about books and bookshelves,
because a book is something completely different
from a bookshelf.
A bookshelf can contain books, but one isn't the other.
The technical reason why this breaks down
is because you've got this book class that inherits
from bookshelf, but actually you are not using inside it
anything about the bookshelf.
So you are completely overriding the str method
because you don't want anything to do with bookshelves
in there and you actually don't need these at all
because I mean, what's the point of setting the quantity
if you're not going to use it in the methods?
So the conceptual reason is a book is not a bookshelf.
The technical reason is there is no reason
to inherit if you're not gonna use
that inheritance anywhere.
So this is where composition comes in.
Composition is for when you wanna say something like,
a bookshelf has many books.
A bookshelf is composed of a bunch of things and books.
So instead of defining our bookshelf and our book like this,
we're going to define it slightly differently.
Instead of setting the quantity of books in the bookshelf,
we're actually going to allow the constructor
to take in a number of books.
So we will do star books
and then we'll say self.books, equal books.
And then here we will say bookshelf with len of self.books.
So what this will take in is a bunch of book objects.
Next up, the book class doesn't actually need,
I'm going to delete this as well for now,
the book class doesn't need to inherit from bookshelf
and it doesn't need the quantity
and it doesn't need to call the superclass of anything.
Okay.
So now we have two much simpler classes,
but how do you use them?
Well, we can create our book
and then we can create another book.
Just like that.
So we have our two books here.
Then we'll create our bookshelf and give it the two books.
Then we can print the shelf.
So I'll press play now and you can see
that you get bookshelf with two books printed out.
This is composition and this is very common,
much more common than inheritance.
It is when you have a class that contains
a bunch of other classes or a class
that has as many of that.
And the here we've got our bookshelf that has many books.
And when you use it, when you create it,
you can pass to it a bunch of your other book objects.
So to recap.
Inheritance means that a book is a bookshelf,
composition means that a bookshelf has many books.
So take your pick from those two,
that's an important decision to make, but as I said earlier,
you'll most frequently be using composition.
Thanks for joining me in this video
to learn about composition in Python,
and I'll see you in the next one.