Bug #52330 [Opn->Wfx]: __construct() method should always return a new instance

From: Date: Tue, 13 Jul 2010 16:34:09 +0000
Subject: Bug #52330 [Opn->Wfx]: __construct() method should always return a new instance
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-152371@lists.php.net to get a copy of this message
Edit report at http://bugs.php.net/bug.php?id=52330&edit=1

 ID:          52330
 Updated by:  aharvey@php.net
 Reported by: whistl0r+phpbug at googlemail dot com
 Summary:     __construct() method should always return a new instance
-Status:      Open
+Status:      Wont fix
 Type:        Bug
 Package:     Class/Object related
 PHP Version: Irrelevant

 New Comment:

That might seem odd, but it seems consistent enough to me. It breaks
down one of two ways:

1. You call the constructor by instantiating an object with new. It
behaves like a constructor -- return values are ignored and a new object
instance is created.

2. You call the constructor by calling $object->__construct(). It
behaves like a method call, including return values being returned.

Basically, if you don't want __construct() to act like a method call,
don't call it like a method call.


Previous Comments:
------------------------------------------------------------------------
[2010-07-13 16:35:38] whistl0r+phpbug at googlemail dot com

Description:
------------
Please see the test script. This should be normal PHP 5.3 class with a
good OOP design.

In PHP it is possible, that I can call the constructor multiple times,
for example:

$person = new \My\Person('Jens', 'Mander');
echo sprintf('Name: %s %s', $person->getName(), $person->getSurname());
// Will output "Name: Jens Mander"

$person->__construct('John', 'Doe');
echo sprintf('Name: %s %s', $person->getName(), $person->getSurname());
// Will output "Name: John Doe"

In my understanding, it is unexpected, that
1) you can access the constructor method in an instantiated object. The
constructor should only instantiate the object - when you have the
object, there is no need to call it again. If you need something to
"reset" your object state, you should implement such a method.

2) If you can call the constructor again, that it will change the object
and *not* return a new instance.

For example:
If you add a "return new \stdClass();" line to your constructor, it will
still change the instance you called it from, but now it will also
return a "stdClass" - that's inconsistent, isn't it?

Test script:
---------------
<?php
namespace My;

class Person
{
  protected $_name = null;
  
  protected $_surname = null;
  
  /**
  * Constructor.
  * 
  * @param  string OPTIONAL $name
  * @param  string OPTIONAL $surname
  * @return \My\Person
  */
  public function __construct($name = null, $surname = null)
  {
    if ($name !== null)
    {
    	$this->setName($name);
    }
    
    if ($surname !== null)
    {
    	$this->setSurname($surname);
    }
  }
  
  /**
  * Returns the name.
  * 
  * @return null|string Null, when no name was set
  */
  public function getName()
  {
    return $this->_name;
  }
  
  /**
  * Returns the surname.
  * 
  * @return null|string Null, when no name was set
  */
  public function getSurname()
  {
    return $this->_surname;
  }
  
  /**
  * Set the name.
  * 
  * @param  string $name
  * @return \My\Person Provides fluent interface
  * @throws \Exception
  */
  public function setName($name)
  {
    if (!is_string($name) || empty($name))
    {
      throw new \Exception('Name cannot be empty and must be a
string!');
    }
    
    $this->_name = $name;
    
    
    return $this;
  }
  
  /**
  * Set the surname.
  * 
  * @param string $name
  * @return \My\Person Provides fluent interface
  * @throws \Exception When $name isn't a string or empty
  */
  public function setSurname($name)
  {
    if (!is_string($name) || empty($name))
    {
      throw new \Exception('Name cannot be empty and must be a
string!');
    }
    
    $this->_surname = $name;
    
    
    return $this;
  }
}

Expected result:
----------------
- FATAL error e.g. "Object already constructed!"

- The __construct() call should return a *new* object.

Actual result:
--------------
The __construct() method will work on the object, from where you called
it.


------------------------------------------------------------------------



-- 
Edit this bug report at http://bugs.php.net/bug.php?id=52330&edit=1


Thread (3 messages)

« previous php.bugs (#152371) next »