Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

This lesson is for members only. Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

Hint: You can adjust the default video playback speed in your account settings.
Hint: You can set your subtitle preferences in your account settings.
Sorry! Looks like there’s an issue with video playback 🙁 This might be due to a temporary outage or because of a configuration issue with your browser. Please see our video player troubleshooting guide to resolve the issue.

Composition to Change Runtime Behavior

00:00 You saw before that inheritance creates a tightly-coupled relationship. If we want to change the behavior in the derived class, we must override a method inherited from the base class.

00:14 This is helpful in certain circumstances, but it creates rigid designs that are hard to change moving forward. Composition, on the other hand, creates a loosely-coupled relationship that enables flexible designs and can be used to change behavior at run-time.

00:34 Let’s say that requirements change and now we need to support a longterm disability policy, or LTD policy, for short. This policy states that an employee on LTD should be paid 60% of their weekly salary, assuming 40 hours per week.

00:56 Adding this to our current design won’t be too hard. I’m going to start by entering hr.py and in here, I’ll create a new class called LTDPolicy.

01:10 This class will expose the same interface as PayrollPolicy, but I don’t want to inherit its method implementations, so I’m not going to inherit from it. It will look similar, though.

01:25 First, I will initialize it with a ._base_policy, which will start as None type. This ._base_policy is the policy the employee had before going on LTD.

01:39 The new pay will be 60% of this. To follow the interface in the PayrollPolicy, we also need a .track_work() method, which will accept the number of hours to work and then track employees for that time.

01:57 This ._check_base_policy() is a method we’ll implement in a moment, which will check to make sure that the ._base_policy attribute is not None.

02:08 If it isn’t, execution will continue, but if it is None, an exception will be raised. If everything checks out, we’ll track the work using the ._base_policy.

02:22 We’ll follow similar steps for the .calculate_payroll() method. We’ll check the ._base_policy, and if that checks out okay, we’ll get the employee’s normal base_salary and return 60% of that. Because I marked the ._base_policy instance attribute as private, I’ll create a method that we can use to set a new base policy.

02:50 All that’s left to do now is implement the ._check_base_policy() method, which will raise a RuntimeError in the event that a base policy is missing.

03:02 Now we can utilize this new class by adding just one more method to the Employee class. I’ll move over to employee.py and at the bottom of that class, I will create a method called .apply_payroll_policy().

03:21 This method will take in a new payroll policy to apply, which will be the LTDPolicy, and then store the existing policy within that new_policy object.

03:36 Then, it’ll set the current ._payroll value to the new_policy. Finally, we can modify the main program module to try this new feature out.

03:49 I’m going to delete everything except our imports and the employees list. I want to modify the third employee in the list to give him this new LTDPolicy.

04:03 The third employee in the database, the sales employee, can be accessed at the second index in the employees list.

04:13 Now that we’ve got that employee, let’s create the longterm disability policy and apply it to them.

04:24 They now have a longterm disability policy applied to them, which itself remembers their old payroll policy and uses that to calculate their new salary. And before I run this, I’m going to make sure to import this new class from the hr module so we don’t see any more exceptions in this course.

04:52 Notice now that our sales employee, Kevin Bacon—with the coolest name ever—previously made $1,800, but now he only makes 60% of that. As you can see, you were able to support this change just by adding a new policy and modifying a couple of interfaces.

05:13 This is the kind of flexibility that policy-based design gives you.

Become a Member to join the conversation.