생성자와 소멸자

생성자

__construct(mixed ...$values = ""): void
                

PHP를 사용하면 개발자가 클래스에 대한 생성자 메서드를 선언할 수 있습니다. 생성자 메서드가 있는 클래스는 새로 생성된 각 개체에서 이 메서드를 호출하므로 개체가 사용되기 전에 필요할 수 있는 초기화에 적합합니다.

메모: 자식 클래스가 생성자를 정의하는 경우 부모 생성자는 암시적으로 호출되지 않습니다. 부모 생성자를 실행하려면 자식 생성자 내에서 parent::__construct()를 호출해야 합니다. 자식이 생성자를 정의하지 않으면 일반 클래스 메서드와 마찬가지로 부모 클래스에서 상속될 수 있습니다(private으로 선언되지 않은 경우).

예제 #1 상속의 생성자

이 예제는 MyClass1.php 및 MyClass2.php 파일에서 각각 MyClass1 및 MyClass2 클래스를 로드하려고 시도합니다.

                  
<?php
class BaseClass {
    function __construct() {
        print "In BaseClass constructor\n";
    }
}

class SubClass extends BaseClass {
    function __construct() {
        parent::__construct();
        print "In SubClass constructor\n";
    }
}

class OtherSubClass extends BaseClass {
    // inherits BaseClass's constructor
}

// In BaseClass constructor
$obj = new BaseClass();

// In BaseClass constructor
// In SubClass constructor
$obj = new SubClass();

// In BaseClass constructor
$obj = new OtherSubClass();
?>
                  
                

다른 메서드와 달리 __construct()는 확장될 때 일반적인 서명 호환성 규칙에서 제외됩니다.

생성자는 해당 객체를 인스턴스화하는 동안 호출되는 일반적인 메서드입니다. 따라서, 그들은 필요할 수 있고, 유형을 가질 수 있고, 기본값을 가질 수 있는 임의의 수의 인수를 정의할 수 있습니다. 생성자 인수는 클래스 이름 뒤의 괄호 안에 인수를 배치하여 호출됩니다.

예제 #2 생성자 인수 사용

                  
<?php
class Point {
    protected int $x;
    protected int $y;

    public function __construct(int $x, int $y = 0) {
        $this->x = $x;
        $this->y = $y;
    }
}

// Pass both parameters.
$p1 = new Point(4, 5);
// Pass only the required parameter. $y will take its default value of 0.
$p2 = new Point(4);
// With named parameters (as of PHP 8.0):
$p3 = new Point(y: 5, x: 4);
?>
                  
                

클래스에 생성자가 없거나 생성자에 필수 인수가 없으면 괄호를 생략할 수 있습니다.

구식 생성자

PHP 8.0.0 이전에는 전역 네임스페이스의 클래스가 클래스와 동일한 이름의 메서드를 구식 생성자로 해석합니다. 해당 구문은 더 이상 사용되지 않으며 E_DEPRECATED 오류가 발생하지만 여전히 해당 함수를 생성자로 호출합니다. __construct()와 같은 이름의 메서드가 모두 정의되어 있으면 __construct()가 호출됩니다.

네임스페이스가 있는 클래스 또는 PHP 8.0.0의 모든 클래스에서 클래스와 동일한 이름의 메서드는 특별한 의미가 없습니다.

새 코드에서는 항상 __construct()를 사용하십시오.

Constructor Promotion

PHP 8.0.0부터 생성자 매개변수도 객체 속성에 해당하도록 승격될 수 있습니다. 생성자 매개변수가 생성자의 속성에 할당되지만 그렇지 않으면 작동되지 않는 것은 매우 일반적입니다. 생성자 승격은 해당 사용 사례에 대한 약칭을 제공합니다. 위의 예는 다음과 같이 다시 작성할 수 있습니다.

예제 #3 생성자 속성 승격 사용

                  
<?php
class Point {
    public function __construct(protected int $x, protected int $y = 0) {
    }
}
                  
                

생성자 인수에 가시성 수정자가 포함되어 있으면 PHP는 이를 객체 속성과 생성자 인수로 해석하고 속성에 인수 값을 할당합니다. 그러면 생성자 본문이 비어 있거나 다른 명령문이 포함될 수 있습니다. 인수 값이 해당 속성에 할당된 후에 추가 명령문이 실행됩니다.

모든 인수를 승격할 필요는 없습니다. 승격된 인수와 승격되지 않은 인수를 순서에 관계없이 혼합하여 일치시킬 수 있습니다. 승격된 인수는 생성자를 호출하는 코드에 영향을 주지 않습니다.

메모: 도입할 엔진 모호성으로 인해 개체 속성을 호출 가능한 형식으로 지정할 수 없습니다. 따라서 승격된 인수도 호출 가능하지 않을 수 있습니다. 그러나 다른 모든 유형 선언이 허용됩니다.

메모: 승격된 생성자 인수에 배치된 Attributes은 속성과 인수 모두에 복제됩니다.

정적 생성 방법

PHP는 클래스당 하나의 생성자만 지원합니다. 그러나 어떤 경우에는 개체가 다른 입력을 사용하여 다른 방식으로 구성되도록 하는 것이 바람직할 수 있습니다. 권장되는 방법은 정적 메서드를 생성자 래퍼로 사용하는 것입니다.

예제 #4 정적 생성 방법 사용

                  
<?php
class Product {

    private ?int $id;
    private ?string $name;

    private function __construct(?int $id = null, ?string $name = null) {
        $this->id = $id;
        $this->name = $name;
    }

    public static function fromBasicData(int $id, string $name): static {
        $new = new static($id, $name);
        return $new;
    }

    public static function fromJson(string $json): static {
        $data = json_decode($json);
        return new static($data['id'], $data['name']);
    }

    public static function fromXml(string $xml): static {
        // Custom logic here.
        $data = convert_xml_to_array($xml);
        $new = new static();
        $new->id = $data['id'];
        $new->name = $data['name'];
        return $new;
    }
}

$p1 = Product::fromBasicData(5, 'Widget');
$p2 = Product::fromJson($some_json_string);
$p3 = Product::fromXml($some_xml_string);
                  
                

생성자는 비공개로 만들거나 외부에서 호출되는 것을 방지하기 위해 보호될 수 있습니다. 그렇다면 정적 메서드만 클래스를 인스턴스화할 수 있습니다. 동일한 클래스 정의에 있기 때문에 동일한 개체 인스턴스가 아니더라도 개인 메서드에 액세스할 수 있습니다. 개인 생성자는 선택 사항이며 사용 사례에 따라 의미가 있을 수도 있고 그렇지 않을 수도 있습니다.

그런 다음 세 가지 공용 정적 메서드가 개체를 인스턴스화하는 다양한 방법을 보여줍니다.

  • fromBasicData()는 필요한 정확한 매개변수를 취한 다음 생성자를 호출하고 결과를 반환하여 객체를 생성합니다.
  • fromJson()은 JSON 문자열을 받아들이고 자체적으로 사전 처리를 수행하여 생성자가 원하는 형식으로 변환합니다. 그런 다음 새 개체를 반환합니다.
  • fromXml()은 XML 문자열을 받아 사전 처리한 다음 베어 객체를 생성합니다. 생성자는 여전히 호출되지만 모든 매개변수가 선택사항이므로 메소드는 이를 건너뜁니다. 그런 다음 결과를 반환하기 직전에 개체 속성에 값을 할당합니다.

세 가지 경우 모두 static 키워드는 코드가 있는 클래스의 이름으로 변환됩니다. 이 경우에는 Product.

소멸자(Destructor)

__destruct(): void
                

PHP는 C++와 같은 다른 객체 지향 언어와 유사한 소멸자 개념을 가지고 있습니다. 소멸자 메서드는 특정 개체에 대한 다른 참조가 없는 즉시 또는 종료 시퀀스 중에 임의의 순서로 호출됩니다.

예제 #3 소멸자 예제

                  
<?php

class MyDestructableClass
{
    function __construct() {
        print "In constructor\n";
    }

    function __destruct() {
        print "Destroying " . __CLASS__ . "\n";
    }
}

$obj = new MyDestructableClass();
                  
                

생성자와 마찬가지로 부모 소멸자는 엔진에 의해 암시적으로 호출되지 않습니다. 부모 소멸자를 실행하려면 소멸자 본문에서 명시적으로 parent::__destruct()를 호출해야 합니다. 또한 생성자와 마찬가지로 자식 클래스는 자체적으로 구현하지 않는 경우 부모의 소멸자를 상속할 수 있습니다.

소멸자는 exit()를 사용하여 스크립트 실행이 중지된 경우에도 호출됩니다. 소멸자에서 exit()를 호출하면 나머지 종료 루틴이 실행되지 않습니다.

메모: 스크립트 종료 중에 호출된 소멸자는 HTTP 헤더가 이미 전송되었습니다. 스크립트 종료 단계의 작업 디렉토리는 일부 SAPI(예: Apache)와 다를 수 있습니다.

메모: 소멸자(스크립트 종료 시 호출됨)에서 예외를 throw하려고 하면 치명적인 오류가 발생합니다.