benanamen Posted January 19, 2017 Share Posted January 19, 2017 I read the manual and numerous other resources on Abstract classes. Abstract classes appear to be very similar to Interface classes. When should I use an Abstract Class instead of an Interface Class? Should ALL classes that are not implementing an interface be programmed against an Abstract Class? If not, what decides that a class should not be derived from an Abstract Class nor an Interface Class? Quote Link to comment Share on other sites More sharing options...
requinix Posted January 19, 2017 Share Posted January 19, 2017 "Abstract" is an adjective. "Class" is a noun. "Interface" is a noun. An "abstract class" is a type of class. An "interface class" is nonsense. Abstract classes and interfaces have similar purposes, yes, but there's one big difference: whether you can put code in it. Use an interface if you want a class to look a certain way but don't care how it actually goes about doing that. The power of an abstract class comes when you want more than one class to look a certain way, they'll all behave a little differently from each other, but you know there will be some code that works the same in all of them and don't want to have to repeat it everywhere. // I don't care how these classes work, but they need do specific methods in them interface IBinaryMathOperator { public function __construct($a, $b); public function getOperandA(); public function getOperandB(); public function operate(); } // most classes will behave similarly so I want to put the common code in one place abstract class BinaryMathOperator implements IBinaryMathOperator { public function __construct($a, $b) { $this->a = $b; $this->b = $b; } public function getOperandA() { return $this->a; } public function getOperandB() { return $this->b; } // don't know about this one yet public abstract function operate(); } // this class is a lot like others but does have some differences that show up in here class AdditionMathOperator extends BinaryMathOperator { public function operate() { return $this->a + $this->b; } }IMO abstract classes that don't have any code don't make sense, so don't bother thinking about them: either do an interface or add some code in it somewhere (if sensible). Quote Link to comment Share on other sites More sharing options...
Jacques1 Posted January 19, 2017 Share Posted January 19, 2017 Abstract classes are partial implementations. You use it when you want multiple implementation which share some common method definitions. This is rare and only relevant for edge cases. As I already said, all classes should implement an interface, either directly or indirectly though an ancestor. You always start with an interface which defines the API. And while you write your implementations, you may in a few rare cases realize that some method definitions are always the same and should be put into an abstract parent class rather than repeated. Quote Link to comment Share on other sites More sharing options...
benanamen Posted January 19, 2017 Author Share Posted January 19, 2017 (edited) You always start with an interface which defines the API. And while you write your implementations, you may in a few rare cases realize that some method definitions are always the same and should be put into an abstract parent class rather than repeated. That makes way more sense then everything I have read about it in the last two days. Edited January 19, 2017 by benanamen Quote Link to comment Share on other sites More sharing options...
requinix Posted January 19, 2017 Share Posted January 19, 2017 This is rare and only relevant for edge cases.For "rare edge cases" they sure get used a lot. If you find yourself almost never using abstract classes then either you've got more code duplication going on than you know about or your codebase is designed much more vertically (long inheritance hierarchies) than it is horizontally (using polymorphism). As I already said, all classes should implement an interface, either directly or indirectly though an ancestor.Classes that represent some sort of functionality, and then I'd say no more than 50% of the average codebase at an extreme. Throwing around interfaces for the sake of, what, dependency injection? is as much an anti-pattern as singletons and registries. Quote Link to comment Share on other sites More sharing options...
benanamen Posted January 19, 2017 Author Share Posted January 19, 2017 I saw this image representing an Abstract Class example and something clicked. Would it be correct to liken an Abstract Class and even a Interface to DB normalization? This image sure looks like it. Source http://www.zentut.com/php-tutorial/php-abstract-class/ Quote Link to comment Share on other sites More sharing options...
Jacques1 Posted January 19, 2017 Share Posted January 19, 2017 (edited) For "rare edge cases" they sure get used a lot. Design-by-popular-vote? Oh my. According to that metric, the top PHP pattern is the SQL injection vulnerability. No wonder the whole world makes fun of us. Edited January 19, 2017 by Jacques1 Quote Link to comment Share on other sites More sharing options...
Jacques1 Posted January 19, 2017 Share Posted January 19, 2017 (edited) Would it be correct to liken an Abstract Class and even a Interface to DB normalization? Not really. I don't think this metaphor is particularly helpful. You can think of an interface as a specification, a class as a concrete blueprint and an instance as a product manufactured according to the blueprint. An abstract class would be half specification, half blueprint. The diagram is actually a great demonstration why skipping the specification part and throwing abstract classes around as suggested by requinix is often a bad idea. As you can see, the Person class makes very special assumptions: The first name and last name are stored in (public) attributes. There's a constructor with no parameters. Your implementation is incompatible with that? You need, for example, lazy loading? Too bad! If you start with a proper specification, this doesn't happen: <?php interface Person { public function getFirstName(); public function getLastName(); public function getSalary(); } This says that a person has a first name, a last name and a salary. How the methods work is completely up to the implementor. Edited January 19, 2017 by Jacques1 Quote Link to comment Share on other sites More sharing options...
benanamen Posted January 19, 2017 Author Share Posted January 19, 2017 (edited) You can think of an interface as a specification, a class as a concrete blueprint and an instance as a product manufactured according to the blueprint. You make it easy for me to grasp this. So would this be the same concept? 1. Client says my DB has to do A,B and C - (Specification=Interface) 2. I create a DB schema (Concrete Blueprint = Class ) 3. The DB (Product manufactured = instance according to blueprint/class) Edited January 19, 2017 by benanamen Quote Link to comment Share on other sites More sharing options...
maxxd Posted January 19, 2017 Share Posted January 19, 2017 But those very special assumptions are the interface. Poor class design (public properties, inflexible constructor, etc.) don't mean the pattern is useless or even bad. Sure, when you use a simple interface, the workings of the methods are up to the concrete classes, but then again they're entirely up to the concrete classes. In this instance, it's a pretty safe bet that both a contractor and an employee have a name. So in both cases, you'll be using toString() (which, in all honestly, should be getName() or something else that actually makes sense - again, it's bad design, not a bad pattern) to print that name. Why write that code in both classes? If the contractor happens to be a corporate entity, create a new CorporateContractor class and overwrite the toString() method there - you're only doing it once, and it's a specific and telling use case. Note the getSalary() method is abstract - if I'm not mistaken, that method has to be implemented in any class that extends from the Person class. So, in effect, it's very similar to your interface except that you're not writing and maintaining the same chunk of code in multiple classes. Quote Link to comment Share on other sites More sharing options...
Jacques1 Posted January 19, 2017 Share Posted January 19, 2017 You've just proven my point. Everything bad about Person stems from the fact that it's an abstract class. And the one potential benefit (reusing a single line of code) is so utterly trivial that it shows how hard you're trying to come up with a legitimate example. Which is exactly what I'm saying: Abstract classes are rarely useful and often abused. That does not mean abstract classes are somehow inherently bad. I'm using them myself in edge cases where there's a significant amount of common code and a trait wouldn't be appropriate. But again, this is rare. Quote Link to comment Share on other sites More sharing options...
kicken Posted January 19, 2017 Share Posted January 19, 2017 You might find this thread over on DevShed a good read. Why Interfaces!? It covers why one might use interfaces and abstract classes. Quote Link to comment Share on other sites More sharing options...
maxxd Posted January 20, 2017 Share Posted January 20, 2017 You've just proven my point. Everything bad about Person stems from the fact that it's an abstract class. And the one potential benefit (reusing a single line of code) is so utterly trivial that it shows how hard you're trying to come up with a legitimate example. Which is exactly what I'm saying: Abstract classes are rarely useful and often abused. That does not mean abstract classes are somehow inherently bad. I'm using them myself in edge cases where there's a significant amount of common code and a trait wouldn't be appropriate. But again, this is rare. Actually, I feel like you've just proven my point. It's easy to dismiss the benefits of consolidating code when taking the simple and frankly rather inane example UML diagram literally, but when you expand to a real-world scope, it makes a lot of sense in some situations. While I'm not saying that abstract classes should always be used, I am saying don't discount them out of hand. In much the same way, I think interfaces are an incredibly useful tool as well, but they don't make sense in all situations and I don't think every class should implement one unless you really, really like typing and (potentially) maintaining the same code in multiple places. Or you're using a framework that builds them for you - I remember Yii would generate skeleton controllers and pretty full models automatically. I'm not using it now, so I don't know if it still does, and I don't know if that's a thing that most frameworks do these days. Quote Link to comment Share on other sites More sharing options...
Jacques1 Posted January 20, 2017 Share Posted January 20, 2017 Can you not understand, or do you not want to understand? I do not “discount abstract classes”. I don't. Wherever you got this idea from, it only exist in your head. Get rid of it, so that we can have a reasonable discussion. I'm saying that abstract classes are one of the less important OOP features and shouldn't be the focus of somebody who is just beginning to learn OOP. Less important. Shouldn't be the focus. Got it? We've discussed a concrete problem, and despite trying hard to justify the use of an abstract class in this scenario, you haven't convinved anybody. To the contrary. Now it's time you draw some conclusions from that. As to interfaces: I understand from your topics and posts in this forum that you have a – how do I say this nicely – rather relaxed attitude towards code quality. OK. This neither surprises nor troubles me. But the topic is about learning proper OOP, and that's definitely not the right place for your hacks. Quote Link to comment Share on other sites More sharing options...
maxxd Posted January 20, 2017 Share Posted January 20, 2017 Well, that escalated quickly... Quote Link to comment Share on other sites More sharing options...
Jacques1 Posted January 20, 2017 Share Posted January 20, 2017 If technical discussions hurt your feelings, maybe you should avoid them in the future. Quote Link to comment Share on other sites More sharing options...
ignace Posted January 21, 2017 Share Posted January 21, 2017 I understand from your topics and posts in this forum that you have a – how do I say this nicely – rather relaxed attitude towards code quality. OK. This neither surprises nor troubles me. But the topic is about learning proper OOP, and that's definitely not the right place for your hacks. Is hardly a technical discussion. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.