Summary
In this episode, we continue our discussion on object-oriented programming practicalities, focusing on interfaces. We explore how interfaces provide a contract among classes, allowing for consistency in intent and communication between objects.
Detailed Notes
Object-oriented programming (OOP) practicalities involve the application of OOP principles to real-world problems. In this episode, we focus on interfaces, which provide a contract among classes, specifying the methods that must be implemented. Interfaces allow for consistency in intent and communication between objects, promoting polymorphism. By using interfaces, developers can create a flexible and reusable code base, reducing code duplication. We explore the benefits of interfaces in enforcing consistency across classes and promoting polymorphism. We also discuss how interfaces can be combined with inheritance to create a robust and maintainable code base.
Highlights
- An interface provides a contract among classes, specifying the methods that must be implemented.
- Interfaces allow for consistency in intent and communication between objects.
- Interfaces can be used to enforce consistency across classes, promoting polymorphism.
- Interfaces can be combined with inheritance to create a flexible and reusable code base.
- Interfaces can help reduce code duplication by providing a common language for objects.
Key Takeaways
- Interfaces provide a contract among classes, specifying the methods that must be implemented.
- Interfaces promote consistency in intent and communication between objects.
- Interfaces can be used to enforce consistency across classes, promoting polymorphism.
- Interfaces can help reduce code duplication by providing a common language for objects.
- Interfaces can be combined with inheritance to create a flexible and reusable code base.
Practical Lessons
- Implement interfaces to enforce consistency across classes.
- Use interfaces to promote polymorphism and reduce code duplication.
- Combine interfaces with inheritance to create a robust and maintainable code base.
Strong Lines
- An interface provides a contract among classes, specifying the methods that must be implemented.
- Interfaces allow for consistency in intent and communication between objects.
- Interfaces can be used to enforce consistency across classes, promoting polymorphism.
Blog Post Angles
- Exploring the benefits of interfaces in enforcing consistency across classes.
- Promoting polymorphism through the use of interfaces.
- Reducing code duplication with interfaces.
- Combining interfaces with inheritance for a robust and maintainable code base.
- Applying interfaces to real-world problems in object-oriented programming.
Keywords
- Object-Oriented Programming
- Interfaces
- Polymorphism
- Consistency
- Code Duplication
Transcript Text
This is Building Better Developers, the Develop-a-Noor podcast. We will accomplish our goals through sharing experience, improving tech skills, increasing business knowledge, and embracing life. Let's dive into the next episode. Well, hello and welcome back. We are continuing our season talking about object-oriented programming practicalities, making it real, finding ways to take these concepts that have really baked into a lot of systems and just really, really reevaluate them and look at where we can make better use of them in our day-to-day development tasks. This episode, we're continuing looking at polymorphism, and I want to spend an episode talking about interfaces. We talk about an interface in a theoretical sense, in an abstract sense, quite a bit. We've talked about the interface into a class, into objects, GUI, graphical user interfaces, things like that. But this is actually a technical structure that exists in some languages, which is the idea of an interface. It's not a class. Typically you'll have a, the syntax will be something along the lines of class and then the name of the class or something like that. An interface would be, essentially you'll say interface and then the name of the interface. It allows us a lot of things in the polymorphic world and really focuses on the polymorphism aspect of object-oriented. In brief, generally what you're going to find, an interface provides when it's part of the is it gives you a way to create a contract among classes. Essentially it says that if a class implements, if it takes advantage of a given interface, then this is what it's going to look like. It's not incredibly different from inheriting because typically when you inherit, you're going to take all of the properties and methods and things like that and say, okay, all of this stuff I'm going to implement or support in some way. I'm either going to just do it as a pass through or I'm going to extend it, I guess, or you could override it. What an interface does is it just tells you what the actual, as the name says, what is the interface into a series of methods essentially. For example, we've talked about print quite a bit. What we would do in an interface, we would have a print that anything would be able to implement. It would use that interface or implement that interface. But the interface itself, that definition says print looks like this. It gives you the signature for print. There's no code behind it. Think of it as one of those old, probably when you were in grade school, you had these templates that you could lay down and you could start coloring in and doing stuff within those. It says that it basically gives you the round hole that you're going to avoid putting a square peg into it. It says here's what this looks like. Here's the name of it. Here are the parameters that we're going to allow for or expect. Here's what's going to be returned. In doing so, this actually gives us a language-enforced mechanism for consistency that we talked about in the prior episode. We talked about being consistent in our intent, in what we're communicating, and what we're allowing the developers to communicate to the classes, the objects essentially that they're working with. An interface allows us to do that in more of a contract fashion, which works really good when you want to do something that goes across a wide range of object types. Again, things like a print or to string or things like that work out perfect for that. You can do it in a base class, but the challenge becomes then that base class, that root class typically would be called object, that everything essentially inherits from or everything would need to inherit from if it wanted this global behavior. Instead it really is a plug-in kind of approach. We can have these multiple interfaces and we can say that our class implements these things. Maybe I want a class that has a save, that does a general save to a database, but I don't care that it's ever going to be printed out. I could use the save interface and skip the print interface. I could have for some things that are more like numerical type objects that have some sort of a value, then maybe in some cases I would be able to do like a, maybe there's an interface that allows me to increment or decrement or to add, to concatenate. Maybe I can concatenate stuff that is string based, but I can't other things. I would only implement that interface if it made sense for my class. This allows us almost the idea, really it's sort of a way to do the concept of multiple objects, but the inheritance part of having properties and things like that that are handled at a base level doesn't exist for the most part for interfaces because they don't have, they're just the template. There's no code behind them. You have to implement it. You have to actually do the work versus the root class. You don't have to. It's already, technically you can just write off of, write on the coattails of whatever was done at that root class and then, or that base class, and then you don't have to do additional coding, which is part of the purpose of inheritance when we start talking about that. But what the interface does give us is a way to provide a common language across our objects. That there are these things, these interfaces, which are effectively our commands. If you go all the way back to when we talked about patterns, software patterns, one of them we talked about was the idea of a command, which is more or less what an interface is. I guess it's almost more a collection of commands typically than just a single command, but nevertheless it is a way to say, essentially sign a class up for supporting a specific command. This actually is one of those things that translates very well into the real world. There's some things that you can ask people to do that they simply have no ability to do so, and others that can do it very well. So maybe like balance my checkbook, and that command includes I'm going to send you a checkbook or a reference to my checkbook. Some people would be, they implement that, they support that interface, others do not. With classes this becomes very important because it allows you to spin through things and look for what they support, what commands they recognize, and either call that command on it or just pass through and say, okay, well if it doesn't support it I'm not going to call it. Or if it doesn't support X then I'm going to see if it supports Y. This is a way to, like I say, enforce consistency across our classes. It does end up being, if you don't use inheritance at all, then you are going to write more code because everything that implements an interface has to implement it. If you use an implement, if you implement or use an interface, then you have to build the code behind it. Now what you can do is you can do with inheritance and interfaces, you could actually have a, you could create some core objects, so in families of objects, families of classes, for example, customer classes. Maybe you have a base customer that implements print, sale, lead, maybe a couple other interfaces that are things that are ways that you treat that data. So now your specific customers, you can have classes that inherit off of that and use that default behavior. When you look at the project and how you've coded it out, I do want to add a little bit of a reality check to it. When you think about it, you probably are not going to create more code dealing with interfaces if you do them right as you would in a normal inheritance, even if multiple inheritance is allowed, which is very rare. Usually interfaces the back doorway because there's all kinds of challenges with multiple inheritance. But you think about it, for example, if I've got a save, just a save function, even if I've got a save function on a class that has a lot of, within its attributes have a lot of classes, then within that, I've got to go through each one and save it. If I don't have native values, then I'm probably going to be spinning through attributes and calling save on those attributes. So I'm going to have to to some extent code specifically for that collection object for lack of a better term. And we're going to have to be able to walk through stuff. Now typically, you may be able to do stuff where you can say if it's a native, then save it one way. If not, then just call save on the object. There are some things you can do there, but at some point you have to probably, you're probably going to have some specific code for that family of classes. Again, it sort of goes back that if you've got a customer, then your customer type classes probably are going to have some sort of account interactions that they're going to be able to work with. And so you're going to have to build and code out that piece, which would be very different from let's say you have a, because you've got customers and maybe you've got like a user, this is an internal user class that also has account related stuff. But it's different, very different stuff as far as what an account is for a user versus what an account is for a customer. And of course, I mean, you can also blur the distinction between those and make it really confusing. There are things that are similar, that are similarly used, but not similar enough that you can reuse a code, which is usually what you're going to run into if you use interfaces correctly is that you find ways to, and especially if you can combine interfaces and inheritance, is you essentially find ways to code for families of stuff and then go down and do the specific classes where there's differences, you code for that, which is how object-oriented should work is you, things that you can code on a very general scale, you do those up at the higher levels of the hierarchy so that the other classes inherit all of that code or at least access to that code. And we'll talk about some other ways to do this in other episodes. But when you do that, that means that the code that's used by everybody, you've got higher up in the hierarchy and then your specialization of the code occurs as you get deeper down into the hierarchy. And so you essentially code just the right amount of code. It's sort of the Goldilocks thing of, okay, this is the one that's just right. I'm not duplicating code wherever I can avoid it. And I'm creating custom code down at the level where it is needed so it doesn't have to get inherited or tagged along throughout a hierarchy unless it's where it's not needed. So those are interfaces, sort of a crash course, some initial thoughts on those. We will definitely be swinging back around talking to those when we get into inheritance and some other things that are out there. But I want to talk about that at this point from the polymorphic point of view of, hey, this is a way for us to enforce the consistency and the language that we want our system to use. Challenge of the Week, are there interfaces supported in your favorite language? And if so, do you use them? If not, take a look at them because I think there's a lot of power in interfaces in certain systems and certain solutions that we're trying to build. And so if you're not comfortable with them, then it would definitely be useful to just get a basic understanding of how they work and implementing them within your language of choice. That being said, we'll wrap this one up and go out there and have yourself a great day, a great week, and we will talk to you next time. Thank you for listening to Building Better Developers, the Developer Noor podcast. For more episodes like this one, you can find us on Apple Podcasts, Stitcher, Amazon, and other podcast venues, or visit our site at developernoor.com. Just a step forward today is still progress. So let's keep moving forward together. There are two things I want to mention to help you get a little further along in your embracing of the content of Developer Noor. One is the book, The Source Code of Happiness. You can find links to it on our page out on the Developer Noor site. You can also find it on Amazon, search for Rob Rodhead or Source Code of Happiness. You can get it on Kindle. If you're an Amazon Prime member, you can read it free. A lot of good information there. That'll be a lot easier than trying to dig through all of our past blog posts. The other thing is our mastermind slash mentor group. We meet roughly every other week, and this is an opportunity to meet with some other people from a lot of different areas of IT. We have a presentation every time. We talk about some cool tools and features and things that we've come across, things that we've learned, things that you can use to advance your career today. Just shoot us an email at info at developernoor.com if you would like more information. Now go out there and have yourself a great one.