00:00 Before we can start modeling a real software project, we need to talk about one more thing: interfaces. These will show up in our UML diagrams and they’ll make it easier to visualize the relationships between many classes. Conceptually, an interface is a description of an object’s features and behaviors.
00:29 It’s important to note that this is a list of declarations and not implementations. What this means is that an interface will say that some class contains some methods, but it doesn’t specify how they’re implemented or the code that actually makes up those methods. It’s like saying, “All mammals can move.” It doesn’t matter how they move—whether they walk or fly—all they need to do to conform to the interface is to declare that they can move in some way.
01:04 Some languages such as C# and Java have an actual mechanism called an interface, which lists these class members. Python does not have or need this because unlike most other languages, Python supports multiple inheritance, which you will learn about later on. Instead, we’re going to utilize the conceptual idea of interfaces within our UML diagrams to better understand how classes relate to one another.
01:38 And, in case it wasn’t already clear, interfaces in software architecture are completely different than user interfaces that define the actual look of a piece of software. To solidify this idea, let’s see what classes on the right conform to, or implement, an interface.
The interface isn’t in the diagram here, but you can pretend that it lists two methods,
waddle(). In other words, some part of our program needs an object that conforms to that interface, having the ability to quack and waddle. It doesn’t matter how they do it, it just has to know that they can quack and waddle.
It turns out we have three classes that implement this interface. Remember, for a class to implement an interface it must have the members—like the attributes and methods—described in the interface. The interface at hand lists
.waddle() methods, so any class on the right that has these two methods will conform.
So, what classes declare the ability to quack and waddle?
Duck does because we can see that it lists
AttackDuck does too because it inherits those methods from its parent class.
That’s because it does not declare both of the required methods. This little inheritance relationship between
AttackDuck is a great way to explain something called the Liskov substitution principle. Formally, this says that if
S is a subtype, or a child class, of
then objects of type
T may be replaced with objects of type
S without altering any of the desired properties of the program. In other words, anywhere our program expects us to pass in a
Duck object, we can pass in an
AttackDuck object instead.
Why does this work? Because an
AttackDuck is a
Duck. It inherits the interface of the
Duck, and so it’s guaranteed to have the same capabilities that our program is expecting—like, maybe the ability to quack and waddle.
We actually saw this in action before when we created our custom exception class. When we tried to raise it, Python told us that it needs to inherit from
BaseException, so we made our class inherit from
Exception, which is a class that itself inherits from
This meant that our class inherited the interface of
Exception, which already contained the interface for
BaseException. Python expected a
BaseException, but we gave it a custom exception type that conformed to the interface it was expecting, and so we were able to raise the exception with no problem.
05:37 This blew my mind when I first learned about it. As you’ll see later, it’s a good idea to try to follow this Liskov substitution principle when you can. It’ll save you from some inheritance headaches later on.
06:08 If an interface of some class lists its members, then an object instantiated from that class can be passed to any part of the program that’s expecting the same set of those members, or a subset of them.
like, in this case, have its payroll calculated. The interface lists three members that a class must declare to conform, and because those members are present in
PayrollObject, that class conforms. By the Liskov substitution principle, anywhere our program is expecting a class that conforms to
07:30 As you might’ve noticed, interfaces look a little bit different from classes in UML diagrams. They’re usually a different color and they contain the word <<interface>> written between two angled brackets at the top.
08:00 When a class conforms to an interface, we draw a dashed line from the class to the interface, and write implements. To test your understanding of inheritance and interfaces, I’ve come up with a few questions to ask yourself.
As for what
SalaryEmployee is called, that depends on the relation. In relation to
SalaryEmployee is the child class, or the derived class. In relation to
CommissionEmployee, it’s the parent class, or the base class.
The next question asks what interface
Employee exposes. The interface for
Employee lists two attributes,
HourlyEmployee exposes a similar interface, except it includes the
CommissionEmployee inherit from
SalaryEmployee and not
Employee directly? Well, according to this diagram, it looks like the
.calculate_payroll() method in
CommissionEmployee might utilize the
.calculate_payroll() method in
It will provide its own implementation of that method that will automatically hide the implementation of its parent, but it can use its parent as a part of its own implementation, as we will see later on. In the real world, this would mean that a commission employee probably has a salary too, and so we should extend
SalaryEmployee instead of
10:53 Any class that implements, or conforms to, this interface must declare these members. Interfaces aren’t built into Python like in other languages, but we can still use them conceptually as a part of our UML diagrams.
Become a Member to join the conversation.