PHP构造函数的目的
我正在使用类和对象类结构,但不是处于复杂的层次 – 只是类和函数,然后在一个地方实例化。
至于__construct
和__destruct
,请告诉我很简单: 构造函数和析构函数的目的是什么?
我知道学校层面的理论解释,但是我期待着像现实世界中的东西,在哪些情况下我们必须使用它们。
请提供一个例子。
问候
构造函数是在对象初始化之后执行的一个函数(分配内存,复制实例属性等)。 其目的是使对象处于有效状态。
通常情况下,处于可用状态的对象需要一些数据。 构造函数的目的是强制在实例化时将这些数据赋予对象,并禁止没有这些数据的任何实例。
考虑一个简单的类来封装一个string,并且有一个方法返回这个string的长度。 一个可能的实现是:
class StringWrapper { private $str; public function setInnerString($str) { $this->str = (string) $str; } public function getLength() { if ($this->str === null) throw new RuntimeException("Invalid state."); return strlen($this->str); } }
为了处于有效状态,这个函数需要在getLength
之前调用setInnerString
。 通过使用构造函数,可以在调用getLength
时强制所有实例处于良好状态:
class StringWrapper { private $str; public function __construct($str) { $this->str = (string) $str; } public function getLength() { return strlen($this->str); } }
您也可以保持setInnerString
允许在实例化后更改string。
当一个对象即将从内存中释放时,调用析构函数。 通常,它包含清理代码(例如closures对象所持有的文件描述符)。 它们在PHP中很less见,因为脚本执行结束时,PHP会清除脚本所拥有的所有资源。
通过示例学习:
class Person { public $name; public $surname; public function __construct($name,$surname){ $this->name=$name; $this->surname=$surname; } }
为什么这有帮助? 因为不是:
$person = new Person(); $person->name='Christian'; $person->surname='Sciberras';
您可以使用:
$person = new Person('Christian','Sciberras');
哪个代码less,看起来更干净!
注意:正如下面的回答正确的状态,构造/析构函数被用于各种各样的事情,包括:de /初始化variables(尤其是当值是variables),内存分配,不variables(可以被超越)和更干净的代码 我还想指出,“更干净的代码”不仅仅是“糖”,而且增强了可读性,可维护性等。
一个类的构造函数定义了当你从这个类实例化一个对象时会发生什么。 类的析构函数定义了在销毁对象实例时发生的情况。
请参阅PHP构造函数和析构函数手册 :
PHP 5允许开发人员为类声明构造函数方法。 具有构造函数方法的类在每个新创build的对象上调用此方法,因此适用于在使用对象之前可能需要的任何初始化。
和
PHP 5引入了一个类似于其他面向对象语言(如C ++)的析构函数的概念。 只要所有对特定对象的引用都被删除,或者当对象被明确销毁,或者在closures序列中以任意顺序,析构函数方法都会被调用。
实际上,您可以使用构造函数将对象置于最小有效状态。 这意味着您将传递给构造函数的参数分配给对象属性。 如果您的对象使用某些不能直接作为属性指定的数据types,请在这里创build它们,例如
class Example { private $database; private $storage; public function __construct($database) { $this->database = $database; $this->storage = new SplObjectStorage; } }
请注意,为了保持对象的可testing性, 构造函数不应该做任何实际的工作 :
在构造函数中工作,例如:创build/初始化协作者,与其他服务进行通信,以及设置自己状态的逻辑消除了testing所需的接缝,迫使子类/模拟inheritance不需要的行为。 构造函数中的太多工作阻止了实例化或者在testing中改变协作者。
在上面的Example
, $database
是一个协作者。 它有一个自己的生命周期和目的,可能是一个共享实例。 你不会在构造函数中创build这个。 另一方面, SplObjectStorage
是SplObjectStorage
的一个组成部分。 它具有相同的生命周期,不与其他对象共享。 因此,可以在ctor中new
它。
同样,你使用析构函数来清理你的对象。 在大多数情况下,这是不需要的,因为它是由PHP自动处理的。 这就是为什么你会在野外看到更多的东西。
构造函数在您实例化类的实例时运行。 所以,如果你有一个classPerson
:
class Person { public $name = 'Bob'; // this is initialization public $age; public function __construct($name = '') { if (!empty($name)) { $this->name = $name; } } public function introduce() { echo "I'm {$this->name} and I'm {$this->age} years old\n"; } public function __destruct() { echo "Bye for now\n"; } }
展示:
$person = new Person; $person->age = 20; $person->introduce(); // I'm Bob and I'm 20 years old // Bye for now
我们可以通过构造函数参数覆盖初始化的初始值:
$person = new Person('Fred'); $person->age = 20; $person->introduce(); // if there are no other references to $person and // unset($person) is called, the script ends // or exit() is called __destruct() runs unset($person); // I'm Fred and I'm 20 years old // Bye for now
希望这有助于展示构造函数和析构函数被调用的地方,它们对于什么有用?
-
__construct()
可以使用资源或更复杂的数据结构的默认类成员。 -
__destruct()
可以释放文件和数据库句柄之类的资源。 - 构造函数通常用于需要依赖关系的 类组合或构造函数注入 。
我发现在构造函数之前想到new
关键字是最容易理解的:它只是告诉我的variables一个新的数据types的对象将被赋予给他,根据我调用的构造函数和我传入的,我可以定义到达对象的状态。
没有了新的东西,我们就会生活在空虚的土地上,崩溃!
从C ++的立场来看,析构函数是最明显的,如果你没有析构函数方法删除所有指向的内存,它将在程序退出后保持使用,造成客户端操作系统的泄漏和滞后,直到下一次重启。
我确信这里有足够多的好消息,但是另外一个angular度总是对我所注意到的有帮助。