Abstracts and Interfaces
00:10 Sometimes you don’t want to implement the thing, you just want to say what the thing should look like. Consider a file. You want to be able to read and write to the file, but you don’t want to care how that is implemented underneath.
00:34 You can define this kind of interface in two ways: you can build an abstraction that the compiler or interpreter enforces (i.e., if you don’t implement something, an error is thrown), or you can be a little more laissez-faire about it and just document that if you give me something with read and write, it’ll work with my protocol.
00:55 The abstraction concept is built into many object-oriented-first languages. Python is a little more flexible. In practice, you’ll find most folks tend towards the laissez-faire approach, but if you want to get all hardcore object-oriented, there is a class and a decorator that can help you build such a beast.
There are, like, laws about teaching object-oriented coding and examples being based on shapes. You’ve got to obey the law. Here, I’m building an abstract
Shape class that stores a color value in RGB.
Any extender of my
Shape class must provide a
.get_area() method. I indicate this requirement by wrapping the method with the
@abstractmethod decorator. And as Python has no way of not implementing, you just pass on the method. Abstraction notwithstanding, it is still a class.
this error is because
.get_area() doesn’t exist on the
Square. If you’re coming to Python from a strictly typed object-oriented language, this probably makes your skin crawl. Enforcement here is happening at runtime, not compile time.
04:15 Although abstract based classes exist in Python, it’s far more common to just do duck typing. That’s typing based on if it looks like a duck and talks like a duck, well then, let’s treat it like a duck. Hmm, duck l’orange.
04:30 The fancy academic term for this is polymorphism (or close enough between friends). Poly meaning many and morph being formed. This is about objects having many forms or, alternatively, passing different kinds of objects into the same place and treating them equivalently based on their form. Well, it’s been a few minutes.
04:51 Did you take a bet on when you’d hear the next pun? What was the over and dunder? An example of duck typing in practice is implementing these three dunder methods. By doing so, your object is following the sequence protocol, meaning it can be treated like a list, it can be iterated upon, it can have members accessed via square brackets, and you can get at its length. Strings, lists, and tuples all implement this protocol, and you can too.
They just need to know that it can be treated as a sequence. The purpose of the
HexColorContainer is to keep color values. Colors are passed in as separate RGB values and accessed as their hex color equivalent. Inside
.__init__(), I’m using a list to store my content.
That would be the cheating part. The constructor expects zero or more tuples with three items in each, corresponding to RGB values. This chunk of the
.__init__() loops through each of the constructor arguments, grabs their individual parts from the tuple, and passes them to the
.add_color() method as separate values. Speaking of
.add_color(), it proxies the list, adding a hex value for the RGB arguments.
.__len__() is what gets called when
len() is called on the object, another part of the sequence protocol. Once again, I just proxy the list implementation. And finally, in true proxy fashion,
.__iter__(), which gets called when the object participates in an iteration, just forwards to the same method on the list. And that’s the last of the three calls you need to create a sequence.
08:24 By implementing these few methods, I’ve got a specialty container that I can use as a list. Quack. That’s it for part two of the course. In the last lesson, I’ll review what you learned and point you at part three.
Become a Member to join the conversation.