Object composition

Learn this with friends

ComputingIntro to computer science - Python5:215 check-ins

About this video

Object composition means one object has another object, so a complex object can be broken into smaller objects that each do one job. The video shows how to reach nested attributes and methods layer by layer with a playlist of songs, then redesigns a mining game so a character has a separate tool object.

You'll be able to

  • explain object composition as one object having another object.
  • access attributes and methods of a nested object layer by layer with dot syntax and indexing.
  • identify weaknesses of a class that models two concepts at once.
  • describe how composition gives separation of concerns and reusable code.

Key words

object composition
A design where one object has another object stored as one of its attributes.
nested object
An object stored inside another object, such as songs inside a playlist.
dot syntax
Using a dot to reach an object's attribute or method, like song.title or song.play().
separation of concerns
Giving each class one clear job so its logic lives in one place.
delegate
When one object hands a task to another object's method instead of doing it itself.
Transcript

- [Instructor] In programming, when things get too complex, we break it down. We've seen this with functions and with data structures, but how do we break down an object? Well, we just take that one object and turn it into several smaller objects that each focus on one specific job.

We call this concept object composition, where one object has another object. This is just another way of organizing our code. We are nesting an object inside of another object. to access the attributes and methods on that nested object, we just need to take it layer by layer.

So, let's say we have a playlist class and a song class where a playlist has a list of song objects that it stores in the attribute queue. A song has a title and artist attribute and a method play. So, if I have a playlist object K-pop, how do I access the title of the next song?

First layer, we access the queue attribute of our playlist object using dot syntax. That gives us a list of songs. Then, we index into that list to get the next song, which gives us a song object. Then, to access the title attribute of that song object, we use dot syntax again.

And the fun part, if we want, we can combine all of those steps into a single line. If we want to play the next song, we follow the same access pattern, but at the end, instead of accessing the song's title attribute, we call its play method. This gives us a nice separation of concerns, where the playlist class is just responsible for managing songs, or as the song class is where all of the logic lives for playing an actual audio track.

Okay, but really, why is this better than just putting all the logic into a single class? Say we're building a mining game where a character can use different tools to break blocks of the terrain. The effectiveness of that mining action combines the character's strength with the tool's power.

After each mining action, the character's stamina decreases, and the tool's durability decreases until it eventually breaks when it reaches zero. So, if I write that class real quick, we have all of these attributes and a mine method. Now, what are the weaknesses of this approach?

For one, it's kind of confusing because this one class is really modeling two concepts, a person and a tool. Like, whose power is this? What does this mean? Two, in the game characters can find and equip different tools, and this design doesn't make it straightforward to swap out tools.

And three, this code isn't easily reusable. Tools aren't always connected to a character. We might find them in a shop more lying on the ground, but there's no way here to separate out that tool logic. So, you probably get where I'm going with this. We should make a tool class and a character should have a tool object.

So, instead of all this stuff, the character class will take a tool parameter and store that tool as an attribute. Then, we'll take all of these tool related attributes and move them into a tool class. A tool knows when it's broken and it knows how to use itself.

So, then the character class doesn't have to think about this. It can delegate to those tool methods. Then, back in my game logic, I can construct tools separately. They exist as independent entities in the world. My character can equip whatever tool they want, and if they happen to stumble across an awesome new shovel, they can equip that with one quick assignment, and now when they mine, the character will use that tool.

With this clean separation of concerns, our programming team can now independently modify and reuse these two classes. If I want to change the formula for how tools break, I can update the tool class without worrying about the character class. Or, I can even break down my tool class further where a tool has a material object that determines its power and durability.

So, the next time you're designing a program, think about what real world objects you need to model. If your concepts start muddling together or your class starts to get too long, consider how you can use composition to break that class down.

Video © Khan Academy, used under CC BY-NC-SA. Watch on Khan Academy. Puzzicle is not affiliated with Khan Academy.