NotionCommotion Posted January 31, 2017 Share Posted January 31, 2017 Before learning about interfaces, I would often use abstract classes: abstract class MyAbstractClass { abstract public function someMethodToOverride(); public function availableMethod() { //code common to all extender classes which does not need to be duplicated... } } class MyFirstClass extends MyAbstractClass { public function someMethodToOverride() { //code unique to each extending class... } } class MySecondClass extends MyAbstractClass { public function someMethodToOverride() { //code unique to each extending class... } } Now trying to more often use interfaces. It is my understanding that the interface is primarily a guide to the user of the class, while abstract classes are to help the classes author create the class. Does it make sense to use both at the same time? For the above, does it make more sense to add someMethodToOverride() and availableMethod() to MyAbstractClass's interface? Or maybe get rid of MyAbstractClass's abstract method someMethodToOverride(), and just but this method in MyFirstClass's interface? Quote Link to comment Share on other sites More sharing options...
requinix Posted January 31, 2017 Share Posted January 31, 2017 (edited) It is my understanding that the interface is primarily a guide to the user of the class, while abstract classes are to help the classes author create the class.Sounds right to me. Does it make sense to use both at the same time?It's not one question about whether you should use both. It's two questions: one about using interfaces and one about using abstract classes. Interface: Does a class try to promise a certain behavior? Could that behavior exist with another class not in this hierarchy? Is the behavior a secondary aspect to the original class? Does the behavior have a more "can do X" attitude rather than "is a Y"? Abstract: Are you planning to (or at least leaving the door open to) subclass this class? Will there be some amount of code that's probably going to be needed by all subclasses, or at least most of them, but some portion that is not known yet? Edited February 1, 2017 by requinix *to Quote Link to comment Share on other sites More sharing options...
NotionCommotion Posted February 1, 2017 Author Share Posted February 1, 2017 Interface: Does a class try promise a certain behavior? "try promise"? Normally, I would assume this is a typo, but not going to assume anything on this topic. Is the behavior a secondary aspect to the original class? Does the behavior have a more "can do X" attitude rather than "is a Y"? "behavior"? As in methods? "can do X" as in can do arithmetic rather than "is a Y" as in is a calculator? Abstract: Are you planning to (or at least leaving the door open to) subclass this class? Will there be some amount of code that's probably going to be needed by all subclasses, or at least most of them, but some portion that is not known yet? For me, this seems to be the norm and not the exception. Shouldn't we always attempt to centralize script instead of duplicating it? I've heard others voice that abstract classes should rarely be used and am questioning whether I am using them too often. Quote Link to comment Share on other sites More sharing options...
requinix Posted February 1, 2017 Share Posted February 1, 2017 (edited) "try promise"? Normally, I would assume this is a typo, but not going to assume anything on this topic.I tend to revise my posts a few times before posting. Occasionally words get lost. Words such as "to". "behavior"? As in methods? "can do X" as in can do arithmetic rather than "is a Y" as in is a calculator?A calculator has calculator-like behavior, such as "put the current value into temporary memory" or "calculate the result of this expression". A class can be a calculator, and an interface can say that a class behaves like a calculator. interface ISaveRestoreState { public function saveState(): string; public function restoreState(string $state); } interface IEvaluateExpression { public function evaluate(string $expr); } interface ICalculator extends ISaveRestoreState, IEvaluateExpression { } class MobileCalculatorApp implements ICalculator { ... } class DesktopCalculatorApp implements ICalculator { ... } For me, this seems to be the norm and not the exception.Which "this"? Shouldn't we always attempt to centralize script instead of duplicating it? I've heard others voice that abstract classes should rarely be used and am questioning whether I am using them too often.If you find yourself wanting to copy code from one class into a new sibling you're writing then it's easy to pull code out of the one class and into an abstract parent instead, so there's no need to do it ahead of time "just in case". So if you feel better about it, don't use an abstract class until you need it. My experiences may be a bit atypical as I tend to write lower-level code than the average PHP developer. More often than not I will build something from the ground up than from the bottom down, and I have no problem adding an extra class or two because I anticipate a need for them later. Like right now, in my own code I have basically // rendering a thing is a behavior that isn't confined to a particular type of object interface IRenderable { public function render(); public function renderToString(); } // view is a renderable thing abstract class View implements IRenderable { // likely the method that will be implemented by a child public abstract function render(); // I can implement this here so the child doesn't have to public function renderToString() { ob_start(); $this->render(); return ob_get_clean(); } } class StaticFileView extends View { // ... // required implementation public function render() { readfile($this->file); } // I could use View::renderToString, however I can do it more efficiently myself public function renderToString() { return file_get_contents($this->file); } }The whole point of the abstract View is so that child classes don't have to implement renderToString by themselves, even though some may want to. It's a matter of practicality and code reuse. For the most part if code needs to deal with rendering a thing then it will work with the IRenderable interface. Don't worry so much about all this. You're asking questions that are best answered with experience and that can't always be expressed in words. Do something for a while and think about how it worked out; if you decide it was really bad then you can go back and refactor, but if it really was that bad then you would probably have realized sooner so it's not actually as bad as you think. Edited February 1, 2017 by requinix Quote Link to comment Share on other sites More sharing options...
Jacques1 Posted February 1, 2017 Share Posted February 1, 2017 (edited) I've heard others voice that abstract classes should rarely be used and am questioning whether I am using them too often. If you need the particular features offered by an abstract class, use an abstract class. This is perfectly fine. The point is that the main tools in OOP are still interfaces and concrete classes. When programmers use abstract classes a lot, that can indicate the hammer syndrome (“When all you have is a hammer, everything looks like a nail.”). Remember when you used lambdas for almost every task and came up with strange solutions to simple problems? That's what I mean. Abstract classes are just one option. Sometimes a concrete base class works just as well. Sometimes a Trait is more useful. And sometimes it makes sense to just duplicate the code. Building complex class hierarchies and writing dozens of lines of OOP boilerplate code only to reuse a few lines of functional code is obviously not very clever. So this is neither about avoiding abstract classes nor about desparately trying to find ways to put them into your code. It's about knowing the whole spectrum of tools. Edited February 1, 2017 by Jacques1 Quote Link to comment Share on other sites More sharing options...
requinix Posted February 1, 2017 Share Posted February 1, 2017 Sometimes a Trait is more useful.Maybe someday they'll be even more useful 1 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.