Mad_Griffith Posted December 6, 2018 Share Posted December 6, 2018 (edited) Hi, I can't understand what I am doing wrong. It keeps on loading endlessly. Can you help out? I have one file with this: require_once 'path/to/firstclass'; $Core = new FirstClass(); Then in second file I have this: require_once 'SecondClass.php'; class FirstClass { public function __construct() { $SecondClass = new SecondClass(); } } In a third file I have this: class SecondClass { public function __construct() { require_once 'path/to/thirdclass'; $ThirdClass = new ThirdClass(); $ThirdClass->secondMethod(); } public function firstMethod() { echo 'my first method!'; } } And in a fourth file I have this: class ThirdClass extends SecondClass { public function secondMethod() { $this->firstMethod(); } } Thank you. Edited December 6, 2018 by Mad_Griffith Link to comment Share on other sites More sharing options...
justsomeguy Posted December 6, 2018 Share Posted December 6, 2018 That's all of your code? What error message do you get? Link to comment Share on other sites More sharing options...
Mad_Griffith Posted December 6, 2018 Author Share Posted December 6, 2018 (edited) It's the bare bone of my code and all I am getting is what appears to be an infinite loop. Edited December 6, 2018 by Mad_Griffith Link to comment Share on other sites More sharing options...
Funce Posted December 6, 2018 Share Posted December 6, 2018 (edited) Would the ThirdClass be inheriting the SecondClass' constructor, and infinitely trying to make new instances of ThirdClass? Edited December 6, 2018 by Funce Link to comment Share on other sites More sharing options...
Mad_Griffith Posted December 6, 2018 Author Share Posted December 6, 2018 (edited) You're right, that's the issue. How can I avoid this in such a way that I am not forced to put an empty constructor in ThirdClass? Should I just use a check on the class in the SecondClass' constructor or is there a better solution? Edited December 6, 2018 by Mad_Griffith Link to comment Share on other sites More sharing options...
Funce Posted December 6, 2018 Share Posted December 6, 2018 Empty constructors aren't inherently bad. I wouldn't see an issue with it. Link to comment Share on other sites More sharing options...
Mad_Griffith Posted December 6, 2018 Author Share Posted December 6, 2018 ThirdClass is something I would like to keep clean, if possible. I will put a check on the class in SecondClass' constructor. Anyway, thank you, I didn't know constructors are inherited. Link to comment Share on other sites More sharing options...
Funce Posted December 6, 2018 Share Posted December 6, 2018 No worries, but if you put a check in SecondClass, you're undermining the point of using classes. It makes SecondClass on its own (and anything else that inherits from it) have more baggage. Link to comment Share on other sites More sharing options...
justsomeguy Posted December 6, 2018 Share Posted December 6, 2018 The constructor is only inherited if you don't define one, so the solution is to define a constructor. If you have a constructor and want to call the parent constructor explicitly you can use parent:: for that. That is often the case, but the parent constructor is not called automatically because sometimes you want to parent constructor to run either before or after the child constructor, so that behavior is left up to the programmer to do explicitly. So the behavior you are expecting is the default behavior when you have a constructor. Therefore, it sounds like the solution is to make a constructor. Link to comment Share on other sites More sharing options...
Mad_Griffith Posted December 7, 2018 Author Share Posted December 7, 2018 (edited) uhm, I get your points. What do you think of this solution? firstMethod() is actually just a init function containing stuff that SecondClass won't share with any other class. public function __construct() { if (get_class($this) !== 'SecondClass') return; $this->firstMethod(); } Edited December 7, 2018 by Mad_Griffith Link to comment Share on other sites More sharing options...
Mad_Griffith Posted December 7, 2018 Author Share Posted December 7, 2018 (edited) I just noticed I am in a conundrum. in firstMethod() I am also setting the value of a few SecondClass' variables that I want to be accessible in ThirdClass, but which of course is not set in ThirdClass if I either add the check in the SecondClass' constructor or override the constructor in ThirdClas. How do I overcome that? Thank you. Edited December 7, 2018 by Mad_Griffith Link to comment Share on other sites More sharing options...
justsomeguy Posted December 7, 2018 Share Posted December 7, 2018 Put a constructor in ThirdClass. Link to comment Share on other sites More sharing options...
Mad_Griffith Posted December 12, 2018 Author Share Posted December 12, 2018 (edited) Hi, I am stuck in a conundrum. I have the following code: class Dad { public function setup() { // sets object and local vars } public function init() { $sonInstance = new $sonName(); $sonInstance->$methodName(); } public function __construct($sonName = null, $methodName = null) { $this->setup($moduleName, $methodName); } } class Son extends Dad { public function doSomething() { } } All this complication is needed because I need to have Dad() flexible enough to call Son() dynamically and be also able to inject the Son's class and method directly (please note that I omitted all the getters and setters on purpose from the code above). $Dad = new Dad(); $Dad->init(); $Son = new Dad('Son', 'doSomething'); $Son->init(); And I need Son extending Dad so that I can access Dad's methods within Son. But doing all this also makes Dad->setup() be called twice. How can I avoid this? What pattern suggestions do you have? Thank you. Edited December 12, 2018 by Mad_Griffith Link to comment Share on other sites More sharing options...
justsomeguy Posted December 12, 2018 Share Posted December 12, 2018 If you don't want to run a function when you call the constructor, then you can't run that function when you call the constructor. This code is a little too abstract to say why you wouldn't want to call the function more than once, but maybe just call it explicitly instead of in the constructor. Maybe use a static property to tell whether or not it's already been called. Maybe use a parameter that determines whether it should be called. Link to comment Share on other sites More sharing options...
Mad_Griffith Posted December 13, 2018 Author Share Posted December 13, 2018 (edited) This is a more faithful code. I need to instantiate Module only once because it can be extended for an indefinite number of times. I hope you can shed some light as I am currently stuck. <?php class Site extends Module { public function indexAction() { echo 'init\'ed!'; } } class Module { public $name; public function getName() { return $this->name; } public function setName($name) { $this->name = $name; } public function getMethod() { return $this->method; } public function setMethod($method) { $this->method = $method; } public function init() { $this->setName('Site'); $this->setMethod('indexAction'); $moduleName = $this->getName(); $methodName = $this->getMethod(); $moduleInstance = new $moduleName(); $moduleInstance->$methodName; } public function __construct() { $this->init(); } } $Module = new Module(); Edited December 13, 2018 by Mad_Griffith Link to comment Share on other sites More sharing options...
justsomeguy Posted December 13, 2018 Share Posted December 13, 2018 I'm a little confused why you're doing it that way. If the only thing the constructor does is call a single method, why isn't that method the constructor? And there's no reason to set and then immediately get the value again. Also, if those are parameters it seems like it would be a little more flexible. class Module { public $name; public function __construct($module, $method) { $this->setName($module); $this->setMethod($method); $moduleInstance = new $module(); $moduleInstance->$method; } public function getName() { return $this->name; } public function setName($name) { $this->name = $name; } public function getMethod() { return $this->method; } public function setMethod($method) { $this->method = $method; } } class Site extends Module { public function __construct() { parent::__construct('Site', 'indexAction'); } } $site = new Site(); Now, what's the issue you were trying to describe before? Are you saying you want multiple module instances but for some reason you only want one of them to instantiate a site instance? This seems a little backwards also. Class A extends class B, but you create an instance of class A inside class B. You're creating an instance of an extended class inside the class that gets extended. What's the point of that? I don't see a reason to do that, why not just instantiate a single instance of site? Why are you explicitly instantiating module at all if you've extended it? Link to comment Share on other sites More sharing options...
Mad_Griffith Posted December 13, 2018 Author Share Posted December 13, 2018 (edited) I am doing it because I would like to have an entry point Class to control all the routing. I would still need to have modules such as Site inherit methods and properties from a superclass, though. Edited December 13, 2018 by Mad_Griffith Link to comment Share on other sites More sharing options...
justsomeguy Posted December 13, 2018 Share Posted December 13, 2018 Right, it makes sense to have a superclass for this, what I don't understand is why you would instantiate a child class inside the superclass. Link to comment Share on other sites More sharing options...
Mad_Griffith Posted December 13, 2018 Author Share Posted December 13, 2018 I need to fire the appropriate Child's method firing: $moduleInstance->$method; Link to comment Share on other sites More sharing options...
justsomeguy Posted December 13, 2018 Share Posted December 13, 2018 And why are you doing that from the superclass and not the child class? I still have no idea why you would instantiate a child class inside a superclass. I don't know what the purpose is. I have never heard of anyone doing that, I haven't even heard of a use case for it. If you think about classes extending other classes, there are multiple analogies. Maybe you have a "food" class. Then you extend the food class to make a "fruit" class. Then you extend the fruit class to make an "apple" class. You're talking about creating an instance of apple from inside the general food class and that makes no sense at all to me why you would want to do that. Why is everything of type "food" required to do something with an apple? If I'm creating an object for rice, or for eggs, why are they messing with apples? It doesn't make sense, the way that's organized does not make sense. Object-oriented programming should be extensible, reusable, and flexible, and when you're creating an instance of a child class inside a superclass you're violating one or more of those goals. The major reason why it doesn't make sense is because the child class presumably implements a set of methods or properties that the superclass does not. That's the point of extensibility. The superclass doesn't know anything about those additional methods or properties. So why does it make sense for the superclass to create an instance of that object and then try to use methods or properties that were not defined in the superclass? Why am I creating an instance of a Food object which immediately tries to remove seeds that might not even be there? Link to comment Share on other sites More sharing options...
Mad_Griffith Posted December 14, 2018 Author Share Posted December 14, 2018 10 hours ago, justsomeguy said: And why are you doing that from the superclass and not the child class? Because I want the Child class to be as clean as possible and somehow abstract that method's firing. Link to comment Share on other sites More sharing options...
justsomeguy Posted December 14, 2018 Share Posted December 14, 2018 If your design goal is to minimize the lines of code in the child class, you're going to end up with a bloated parent class. Maybe you're thinking of some version of a factory pattern where you have a factory class that creates other classes based on what you pass to it. Look into that and see if it applies, but I would recommend not doing anything for any child class inside a parent class. Your goal should be to keep the parent class (and all classes) clean and easy to understand. If you tie things up in a way where you're calling methods from child classes inside parent classes then you're going to make debugging more difficult and you're starting to introduce requirements in your classes which will degrade the reusability and flexibility goals of OOP. Or, at a minimum, move that code which calls some initialization function to the child's constructor instead of the parent's constructor, so that each child class can do whatever it needs to be done. Link to comment Share on other sites More sharing options...
Mad_Griffith Posted December 17, 2018 Author Share Posted December 17, 2018 Thank you so much. I found this resource and I may need a mix of a Factory / FrontController kind of thing, although I am not too keen on abstracting the dispatcher. But the philosophy behind what I am trying to do quite matches the FrontController pattern. Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now