Calling a PHP constructor from its own method
Asked Answered
M

3

6

I've been looking for a way to call a class's constructor that is analogous to "parent::_construct" but for the class itself (something like "self::_construct", though that doesn't work). Why do this? Consider the following (which doesn't work, btw)...

class A {
  var $name;
  function __construct($name) {
    $this->name = $name;
  }
  function getClone($name) {
    $newObj = self::__construct($name);
    return $newObj;
  }
}

class B extends A {
}

In the real implementation there are other properties that will differentiate class B from class A, but both should have the "getClone" method. If called on an object of class A it should yield another object of class A, and if called on class B it should yield another object of class B.

Of course I could do this by just overriding "getClone" in class B and hard-coding the class name into the method (i.e., $newObj = new B($name)), but it would be much nicer to just code the method once, telling it to instantiate an object of its own class, whatever that class may be.

Will PHP let me do this?

Marcusmarcy answered 7/6, 2012 at 6:23 Comment(3)
I shouldn't have called my method "getClone" or implied cloning in any way. The new object might be very different from the one whose method is called, and should not copy any of its progenitor's internal data. So I don't think the built in cloning is right for me.Marcusmarcy
Likewise I don't think "init()" helps bc I still need to generate and return a new obj from within the method and the only way to do that is ultimately by using the constructor. Would love to be shown otherwise. I guess I'm surprised there's no equivalent to "parent" that means "self".Marcusmarcy
There is an equivalent, and it's either self or static, depending on your needs.Radiotherapy
G
4

You can use

 $clsName = get_class($this);
 return new $clsName();

But niko's solution also works, useful for a singleton pattern http://php.net/manual/en/language.oop5.static.php

Starting with php 5.3 you can use new features of the static keyword.

<?php

abstract class Singleton {

    protected static $_instance = NULL;

    /**
     * Prevent direct object creation
     */
    final private function  __construct() { }

    /**
     * Prevent object cloning
     */
    final private function  __clone() { }

    /**
     * Returns new or existing Singleton instance
     * @return Singleton
     */
    final public static function getInstance(){
        if( static::$_instance == null){
            static::$_instance = new static();
        }
        return static::$_instance;
    }
    
}
?>
Gummosis answered 7/6, 2012 at 7:30 Comment(0)
R
2

You can use not only variables but also special class-related keywords such as "self" or "static" to create a new instance: $newObj = new static($name); - this will create a new instance of the current class.

You should probably consider using the build-in support for cloning objects: $copy = clone $instance; - you can easily extend the behavior of that operator on instances of your class by specifying a magic method __clone().

class A {
  var $name;
  function __construct($name) {
    $this->name = $name;
  }
  function getClone($name) {
    $newObj = new static($name);
    return $newObj;
  }
}

class B extends A {
}

$tmp = new A('foo');
$a = $tmp->getClone('bar');
// $a instanceof A => true, $a instanceof B => false

$tmp = new B('foo');
$b = $tmp->getClone('bar');
// $b instanceof A => true, $b instanceof B => true
Radiotherapy answered 7/6, 2012 at 6:35 Comment(0)
D
1

What you want to do is use the built in object cloning functionality http://php.net/manual/en/language.oop5.cloning.php

But for your direct question about recalling constructor, what you should do is make an init() function, and put all of your __constructor code in init() and have __constructor call init()

Discuss answered 7/6, 2012 at 6:29 Comment(1)
Thank you for your answer but I'm not sure it's what I need. Pls. see my new comment above.Marcusmarcy

© 2022 - 2024 — McMap. All rights reserved.