Fairly straightforward question. In C++ the parent constructor will be implicitly called before the child constructor, so what logic is there for PHP not to do things this way?
EDIT: I've got a good answer from Lukman, but I was hoping for more of a reason why there is a difference. Maybe the question should be why does C++ not allow custom calling of parent constructors? I guess that's another question though.
I think it's a good thing that PHP makes you call parent's constructor manually, because it allows child's constructor such as following:
public function __construct() {
// set up variables that parent::__construct() requires
$var1 = get_stuff_from_db();
$var2 = get_stuff_from_webservice();
parent::__construct($var1, $var2);
// continue setting up $this var
$this->default = 'Default';
$this->do_some_secret_stuff();
}
Or even:
public function __construct($param) {
// call differently based on condition
if (is_array($param))
$param['id'] = 0;
parent::__construct($param);
}
else {
parent::__construct($param, 0, TRUE);
}
// continue setting up $this var
$this->default = 'Default';
$this->do_some_secret_stuff();
}
Meaning, you are free to call the parent constructor anywhere within the child's and you are free to do stuff before and after the call. Ain't that a feature indeed?
When you don't have a constructor in the child class, then the parent one is automatically called.
If you decided to add a constructor to the child class, then of course you need to explicitly call the parent constructor. If you are already taking the time to add a constructor to your child class, then adding one more line of code parent::__construct(); doesn't seem to be a big deal. But the overriding is actually a convenient flexibility.
to avoid tight coupling that's why inheritance (extend keyword in java) is evil and interface class is prefered see Javaworld article:
http://www.javaworld.com/javaworld/jw-08-2003/jw-0801-toolbox.html
Still it would be great if there was some instruction to call the parent at some point with a special keyword like forward but I have not yet seen this in any language (even Rebol) except in an unknown language invented by Paul Allen (yeah the co-founder of Microsoft) which is Openscript.
Related
I know in Java, super() in a constructor has to be called as the first line of an overridden constructor.
Does this also apply to the parent::__construct() call in PHP?
I found myself writing an Exception class like this:
class MyException extends Exception {
public function __construct($some_data) {
$message = '';
$message .= format_data($some_data);
$message .= ' was passed but was not expected';
parent::__construct($message);
}
}
and I wondered if this would be considered an error/bad practice in PHP.
If you want the code in the parent's constructor to be executed, you need to call parent::__construct(…) at some point. It does not technically matter when you do so. Sometimes it makes more sense to do a little work in the overridden constructor before calling the parent's constructor, sometimes you rely on work the parent's constructor does before you can do work in the overridden constructor.
As a rule of thumb I'd say you should call the parent's constructor as soon as possible. If you need to do something before you can call the parent's constructor, do so. If not, call it immediately. This is to avoid the parent's constructor undoing any of the work you're doing in the overridden constructor, like setting certain properties for example.
class A {
function __construct() {
$this->foo = 'bar';
}
}
class B extends A {
function __construct() {
// parent::__construct();
$this->foo = 'baz';
// parent::__construct();
}
}
In the above sample, the difference between calling the parent first or last makes a big difference in the resulting object. Which is more appropriate depends on what you're trying to do.
The main question is not whether the call to the parent constructor it should be executed on the first line, or executed at all. Instead it's about what can be considered better practice and why.
Doubling the given answers: yes, you can omit parent::__construct altogether; yes, you can call it from wherever you like inside the __construct function of the child class. And any approach is good, as long as it makes sense and is consistent.
If you have a parent class with three children, for example, and every child uses the parent::__construct call in it's own way, then it can be a flag that the inheritence is not too clear and should be refactored.
If you want to execute the code in the parent's constructor, then the answer is yes. If the child class overwrites the parent's constructor, you should omit it.
I am confused whether to use static method or just simple method.
Lets me give an example, I am using Zend framework 1 project.
I have class like
class Example1
{
public static function getVariable() {
return is_numeric(Zend_Registry::get('config')->Variable) ? Zend_Registry::get('config')->Variable : 0;
}
public function calculateSome($param1, $param2) {
$response = array();
if($param2 == 0) {
$response = number_format(($param1 * self::getvariable()) /100);
} else {
$response = $param1;
}
return $response;
}
}
Usage :
Currently i'm getting variable value like Example1::getVariable() in whole project.
And Calculating like first instantiating a class $class1 = new Example1(); and then calling the function like $class1->calculateSome(1, 0);
I am confused whether it is good to change calculateSome() to public static and call like this Example1::calculateSome(1, 0) or left as it is.
I Have found link when to use static =>
When to use static vs instantiated classes
But I can't understand what it says.
You can find the long answer here: How Not To Kill Your Testability Using Statics
The TL;DR version of it is:
A static method is nothing more than a namespaced function, Foo::bar() does not significantly differ from foo_bar().
Whenever you call a static method, or a function for that matter, you're hardcoding a dependency. The code that reads $bar = Foo::bar(); has a hardcoded dependency to a specific Foo class. It is not possible to change what Foo refers to without changing that part of the source code.
An object is a "soft" dependency. $bar = $foo->bar(); is flexible, it allows room to change what $foo refers to. You use this with dependency injection to decouple code from other code:
function baz(Foo $foo) {
$bar = $foo->bar();
...
}
You can call Foo::bar() anytime from anywhere. If Foo::bar has some dependency it depends on, it becomes hard to guarantee that this dependency is available at the time you're calling the method. Requiring object instantiation requires the object's constructor to run, which can enforce requirements to be set up which the rest of the methods of the object can depend on.
Constructors together with dependency injecting objects into other functions are very powerful to
create seams in your codebase to make it possible to "take it apart" and put it together in flexible ways
put checks into strategic places to ensure requirements are met for certain parts of the code (at object instantiation time the constructor enforces a sane state of its little part of the world, its object), which makes it a lot easier to localise and contain failures.
Think of it like compartmentalising your app and putting firewalls between each compartment with a supervisor in charge of each one; instead of everyone just running around in the same room.
Any time you write new Class, you may as well write Class::staticMethod(), the hardcoded dependency is the same.
So the decision comes down to:
What are the requirements of this class? Does it need to ensure certain preconditions are met before any of its code can run (e.g. a database connection needs to be available), or are all methods just self-contained little helper methods?
How likely are you to maybe want to substitute this class for another class? Does this class produce side effects (e.g. writing to a file, modifying some global state) which may not always be desirable and hence a different version of it may be useful under some circumstances?
May you need more than one instance of this class at the same time, or is the nature of the class such that there are no individual instances needed?
Start using unit tests, which require you to take your app apart and test each little part individually to ensure it works, and you'll see where the advantage of object instantiation and dependency injection lie.
When the method involve instance-based properties/changes u should keep it non-static.
If its a method that is needed for the whole type then use static.
For example u can keep tracks of created instances by this snippet:
class Product {
static $count;
private $name;
public function __construct($name) {
$this->name = $name;
self::$count++;
}
public function getName() {
return $this->name;
}
public static function getCount() {
return self:$count;
}
}
$productA = new Product('A');
$productB = new Product('B');
echo $productA->getName(). ' and ' . $productB->getName(). '<br />'. PHP_EOL;
echo 'Total made products :' . Product::getCount();
I am confused about how "static" and "dynamic" functions and objects in PHP work together especially with regards to __callStatic().
How __callStatic() works:
You can have a normal class MyClass, where within the class you can
put a static function called __callStatic(), which gets called only
when MyClass doesn't have a static function by the name you want.
i.e. I call MyClass::newFunction();
newFunction() is called statically but MyClass does not
have it declared. So, then __callStatic() gets called and
inside you can say
$myObject=new SomeOtherClass();
$myObject->newFunction();
which calls the function you wanted but on some other object.
Short Version:
In other words, __callStatic() does this:
MyClass::newFunction();
which is hiding this:
(new SomeOtherClass())->newFunction();
Say what now? What looks like code calling a static function from a class, turns out to be calling that function from some other class and calling it via instantiation, and not statically.
Explain this, please!
Why was it done? Can you do anything like this elsewhere, like C++ or Java? I am looking for short & concise, but informative explanation on static and dynamic functions in languages, and in this case whether __callStatic() violates or conforms to the big picture of Language constructs. Or is it a new language construct entirely.
__callStatic() provides developers with possibility to react on static method calls even if that methods don't exist or aren't accessible from outside of the class ( being protected). This is useful for dynamic, generic code generation.
Example: You have this class:
class Test {
protected static function myProtected($test) {
var_dump(__METHOD__, $test);
}
public static function __callStatic($method, $args) {
switch($method) {
case 'foo' :
echo 'You have called foo()';
var_dump($args);
break;
case 'helloWorld':
echo 'Hello ' . $args[0];
break;
case 'myProtected':
return call_user_func_array(
array(get_called_class(), 'myProtected'),
$args
);
break;
}
}
}
Try to call:
// these ones does not *really* exist
Test::foo('bar');
Test::helloWorld('hek2mgl');
// this one wouldn't be accessible
Test::myProtected('foo');
Why was it done?
This is an existential question, but I think that the answer is "because you can". PHP is a dynamic language and these constructs __call and __callStatic() show off its power, and this power can be useful in some situations.
Can you do anything like this elsewhere, like C++ or Java?
No. They have no similar magic methods.
I am looking for short & concise, but informative explanation on static and dynamic functions in languages
Static functions encapsulate code. They exist even when no class has been instantiated. You can call them using scope resolution operator.
Dynamic functions are well, dynamic
.. does __callStatic() violate or conform to the big picture of Language constructs. Or is it a new language construct entirely.
It is a construct of a dynamic language. Not sure if this functionality exists in all dynamic languages, but it does in PHP. It does not violate anything, just introduces new paradigm of fall-through catch-all functions when the function you do call does not exist/not accessible in current scope.
I'm not entirely sure why __callStatic() is relevant here?
I don't quite see the difference between:
class Foo {
static function bar() {
$obj = new Foo();
$obj->quux();
}
function quux() {
return "whatever";
}
}
and your example? In both scenarios you're calling a static method which is calling another method on an object of the same class.
Yeah, that's possible. Actually doing it suggests you might want to refactor your code though. In the example you're instantiating an object with its default state, executing a method on it and then throwing the object away. This suggests whatever the method is doing doesn't actually need the objects state. That means it either doesn't belong in this class or could simply be rewritten to be a static method itself.
And are you aware of __call? It does the same thing as __callStatic but for objects rather than classes. E.g. $foo->myMissingMethod(); would go to __call if such a method exists for the class of which $foo is an instance.
I want to clarify a problem i am having
I have a base DataBase class that will be inherited by a bunch of other classes.The constructor looks like this:
public function __construct ($table)
{
$this->table = $table;
$this->db = new Database();
$this->db->connect();
}
I will call from this constructor from children as following:
public function __construct ($something)
{
parent::__construct("planets_games");
}
My problem is that php doesn't allow me to make the child's constructor without the $something parameter
i get the following:
Fatal error: Declaration of planetsGames::__construct() must be compatible with that of IScaffold::__construct()
I am currently bypassing this by instantiating an object like this:
$pg = new planetsGames('uselessStringHereThatHasNoUtilityAtAll');
I think i am missing something very important in my basic php knowledge
Thank you very much for the help in advance
This error message refers to the liskov substitution principle.
It applies to every IS-A relationship (which is the meaning of using inheritance (extends)) and states that every subtype should be fully replacable for the super type.
But this doesn´t apply to constructors! Which php version you are using?
It seems the base class has marked the constructor as abstract. That´s the only way
this error can appear.
You should never mark constructors abstract, final or put them in interfaces!
In most languages this isn´t even possible.
What you should take away from this is that the best-practice is that
each concrete object has a constructor with a signature that best
represents how a consumer should fully instantiate that particular
object. In some cases where inheritance is involved, “borrowing” the
parents constructor is acceptable and useful. Furthermore, it is
encouraged that when you subclass a particular type, that your new
type should, when appropriate, have its own constructor that makes the
most sense to the new subtype.
http://ralphschindler.com/2012/03/09/php-constructor-best-practices-and-the-prototype-pattern
A few years late to the party....
The problem is your constructor is needing a value. You can prevent the fatal error by setting a default value such as an empty string.
public function __construct($something = "")
{
parent::__construct("planets_games");
}
Then just instantiate the class like normal
$pg = new planetsGames();
I was wondering if its possible to call the parents __construct(), before the child's __construct() with inheritance in PHP.
Example:
class Tag {
__construct() {
// Called first.
}
}
class Form extends Tag {
__construct() {
// Called second.
}
}
new Form();
Ideally, I would be able to do something in between them. If this is not possible, is there an alternative, which would allow me to do this?
The reason I want to do this is to be able to load a bunch of default settings specific to the Tag that Form can use when __construct() is called.
EDIT: Sorry forgot to add this.. I'd rather not call the parent class from the child class. It's simply because it exposes some private data (for the parent) to the child, when you pass it as an argument
This is what I want to do:
$tag = new Tag($privateInfo, $publicInfo);
$tag->extend(new Form()); // Ideal function, prob doesn't work with inheritance.
Tag.php
class Tag {
private $privateInfo;
public $publicInfo;
__construct($private, $public) {
$this->privateInfo = $private;
$this->publicInfo = $public;
}
}
Form.php
class Form extends Tag {
__construct() {
echo $this->publicInfo;
}
}
Make sense?
Thanks!
Matt Mueller
Just call parent::__construct in the child.
class Form extends Tag
{
function __construct()
{
parent::__construct();
// Called second.
}
}
yeah just call parent::__construct() in your construct
Yes, but only internally (i.e., by writing a PHP extension), so if I were you I'd settle with calling parent::__construct(). See this section on the PHP wiki.
Sorry, PHP is not Java. I think not requiring (implicitly or explictly) the super constructor to be called was a very poor design decision.
From the sounds of it you may want to rethink your design so that you don't need to pass the parameters in the constructor. If you don't think it can be done, ask it as a question, you might be surprised by some of the suggestions.
The child class has the ability to override the parent constructor without calling it at all. I would recommend having a final method in the parent class. That way everyone knows you don't want this being overriden, and any inherited class (rightly) has access to do whatever it wants in the constructor.
class Father {
private $_privateData;
final function setPrivateData($privateData) {
$this->_privateData = $privateData;
}
}
Another, not recommended, more "reinventing the wheel", solution would be to define a function in the parent class, say _construct(), that's called in its own construct. Its not really clear, doesn't use language features/constructs, and is very specific to a single application.
One last thing to keep in mind: you can't really hide information from the child class. With Reflection, serialize, var_dump, var_export and all these other convenient APIs in the php language, if there is code that shouldn't do anything with the data, then there's not really much you can do asides from not store it. There are libraries and such that help create sandboxes, but its hard to sandbox an object from itself.
Edit: Somehow I missed Artefacto's answer, and I suppose he is right (I've never tried writing an extension to do that). Still, implementing it breaks developer expectations while making it harder to actually see code to explain what's going in.