PHP构造函数的目的

Bha*_*mar 56 php oop constructor class

我正在使用类和对象类结构,但不是在复杂的层次 - 只是类和函数,然后,在一个地方,实例化.

至于__construct__destruct,请告诉我非常简单:构造函数和析构函数的目的是什么?

我知道学校层面的理论解释,但我期待现实世界中的某些东西,就像我们必须使用它们的情况一样.

请提供一个例子.

问候

Art*_*cto 52

构造函数是在初始化对象(分配内存,复制实例属性等)后执行的函数.其目的是将对象置于有效状态.

通常,处于可用状态的对象需要一些数据.构造函数的目的是强制在实例化时将此数据提供给对象,并禁止没有此类数据的任何实例.

考虑一个封装字符串的简单类,它有一个返回该字符串长度的方法.一种可能的实现方式是:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

为了处于有效状态,需要setInnerString先调用此函数getLength.通过使用构造函数,您可以在getLength调用时强制所有实例处于良好状态:

class StringWrapper {
    private $str;

    public function __construct($str) {
        $this->str = (string) $str;
    }

    public function getLength() {
        return strlen($this->str);
    }
}
Run Code Online (Sandbox Code Playgroud)

您还可以保留setInnerString允许在实例化后更改字符串.

当一个对象即将从内存中释放时,将调用析构函数.通常,它包含清理代码(例如关闭对象持有的文件描述符).它们在PHP中很少见,因为PHP会在脚本执行结束时清除脚本所拥有的所有资源.

  • 另一种说法是"将对象置于有效状态"是指"确保对象不变量为真".类的不变量是关于实例的事实总是应该是真的:就像内部str值应该总是初始化一样. (2认同)

Chr*_*ian 42

通过示例学习:

class Person {
  public $name;
  public $surname;
  public function __construct($name,$surname){
    $this->name=$name;
    $this->surname=$surname;
  }
}
Run Code Online (Sandbox Code Playgroud)

为什么这有用?因为而不是:

$person = new Person();
$person->name='Christian';
$person->surname='Sciberras';
Run Code Online (Sandbox Code Playgroud)

您可以使用:

$person = new Person('Christian','Sciberras');
Run Code Online (Sandbox Code Playgroud)

哪个代码少,看起来更干净!

注意:正如下面的回复正确陈述,构造函数/析构函数用于各种各样的事情,包括:de /初始化变量(特别是当值是变量时),内存de /分配,不变量(可以超越)和清洁代码.我还要注意"清洁代码"不仅仅是"糖",还增强了可读性,可维护性等.

  • 它不仅看起来更干净.它可以防止错误:如果忘记设置姓氏会怎样?构造函数强制您执行此操作. (5认同)

Gre*_*g K 8

构造函数在您实例化类的实例时运行.所以,如果你有一个班级Person:

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";
    }
}
Run Code Online (Sandbox Code Playgroud)

展示:

$person = new Person;
$person->age = 20;
$person->introduce();

// I'm Bob and I'm 20 years old
// Bye for now
Run Code Online (Sandbox Code Playgroud)

我们可以通过构造函数参数覆盖初始化的默认值:

$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
Run Code Online (Sandbox Code Playgroud)

希望这有助于演示构造函数和析构函数的调用位置,它们对哪些有用?

  1. __construct() 可以使用资源或更复杂的数据结构来默认类成员.
  2. __destruct() 可以释放文件和数据库句柄等资源.
  3. 构造函数通常用于类组合构造函数注入所需的依赖项.


Gor*_*don 7

类的构造函数定义从此类实例化对象时发生的情况.类的析构函数定义了销毁对象实例时发生的情况.

请参阅PHP构造函数和析构函数手册:

PHP 5允许开发人员为类声明构造函数方法.具有构造函数方法的类在每个新创建的对象上调用此方法,因此它适用于对象在使用之前可能需要的任何初始化.

PHP 5引入了类似于其他面向对象语言的析构函数概念,例如C++.一旦删除了对特定对象的所有引用,或者在关闭序列中显式销毁对象或以任何顺序,就会调用析构函数方法.

实际上,您使用构造函数将对象置于最小有效状态.这意味着您将传递给构造函数的参数分配给对象属性.如果您的对象使用某些不能直接指定为属性的数据类型,则可以在此处创建它们,例如

class Example
{
    private $database;
    private $storage;

    public function __construct($database)
    {
        $this->database = $database;
        $this->storage = new SplObjectStorage;
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,为了使您的对象可测试,构造函数不应该做任何实际的工作:

在构造函数中工作,例如:创建/初始化协作者,与其他服务进行通信以及设置自己状态的逻辑,可以删除测试所需的接口,从而强制子类/模拟继承不需要的行为.构造函数中的太多工作会阻止实例化或更改测试中的协作者.

在上面Example,$database是一个合作者.它具有自己的生命周期和目的,可能是一个共享实例.你不会在构造函数中创建它.另一方面,它SplObjectStorage是不可或缺的一部分Example.它具有完全相同的生命周期,不与其他对象共享.因此,new在ctor中它是可以的.

同样,您使用析构函数来清理对象之后.在大多数情况下,这是不必要的,因为它由PHP自动处理.这就是为什么你会看到更多的ctors而不是野外的dtors.