>  기사  >  백엔드 개발  >  PHP 7.4의 유형화된 속성

PHP 7.4의 유형화된 속성

藏色散人
藏色散人원래의
2019-11-30 13:32:114046검색

PHP 7.4에는 유형 속성이 추가되었으며 PHP 유형 시스템이 크게 개선되었습니다. 이러한 변경 사항은 전적으로 선택 사항이며 이전 버전을 손상시키지 않습니다.

이 기사에서는 이 기능을 더 자세히 살펴보겠지만 먼저 가장 중요한 사항을 요약해 보겠습니다.

● PHP 7.4부터 사용할 수 있습니다.

● 클래스에서만 사용할 수 있으며 액세스 한정자가 필요합니다: public, protected 또는 private; 또는 var.

● void 및 callable을 제외한 모든 유형이 허용됩니다

실제 상황은 다음과 같습니다.

class Foo
{
    public int $a;
    public ?string $b = 'foo';
    private Foo $prop;
    protected static string $static = 'default';
}

#Uninitialized

흥미롭게 보기 계속하기 전에 먼저 유형 속성의 중요한 측면에 대해 논의해 보겠습니다.

처음 보는 내용에도 불구하고 다음 코드는 유효합니다:

class Foo
{
    public int $bar;
}
$foo = new Foo;

$bar의 값이 정수가 아니더라도 Foo 개체를 만든 후 PHP는 $bar가 Visit인 경우에만 오류를 발생시킵니다.

var_dump($foo->bar);
Fatal error: Uncaught Error: Typed property Foo::$bar 
must not be accessed before initialization

오류 메시지에서 볼 수 있듯이 초기화되지 않은 새로운 "변수 상태"가 있습니다.

$bar에 유형이 없으면 해당 값은 null이 됩니다. 그러나 유형은 null일 수 있으므로 null 유형의 속성이 설정되었는지 아니면 단순히 잊어버렸는지 알 수 있는 방법이 없습니다. 그래서 "초기화되지 않음"이 추가되었습니다.

초기화 해제에 관해 기억해야 할 네 가지 사항:

● 초기화되지 않은 속성은 읽을 수 없으며, 그렇게 하면 치명적인 오류가 발생합니다.

● 속성에 접근할 때 초기화되지 않은 상태를 확인하기 때문에 해당 유형이 nullable이 아니더라도 초기화되지 않은 속성을 사용하여 객체를 생성할 수 있습니다.

● 초기화되지 않은 속성에 먼저 쓴 다음 읽을 수 있습니다.

● 유형이 지정된 속성에 unset을 사용하면 초기화가 취소되고, 유형이 지정되지 않은 속성을 설정하지 않으면 null이 됩니다.

특히, 다음 코드는 객체를 생성한 후 초기화되지 않고 null을 허용하지 않는 속성이 설정된 경우에 유효하다는 점에 유의하세요

class Foo
{
    public int $a;
}
$foo = new Foo;
$foo->a = 1;

초기화되지 않은 상태는 속성 값을 읽을 때만 확인하지만, 작성할 때는 확인하지 않습니다. 속성 값에 대해 유형 유효성 검사가 수행됩니다. 이는 유효하지 않은 유형이 속성 값으로 끝나지 않도록 할 수 있음을 의미합니다.

#기본값 및 생성자

입력된 값을 초기화하는 방법을 자세히 살펴보겠습니다. 스칼라 유형의 경우 기본값이 제공될 수 있습니다.

class Foo
{
    public int $bar = 4;
    
    public ?string $baz = null;
    
    public array $list = [1, 2, 3];
}

유형이 실제로 비어 있는 경우에만 null을 기본값으로 사용할 수 있습니다. 이는 당연한 것처럼 보이지만 매개변수 기본값에는 다음을 허용하는 일부 오래된 동작이 있습니다.

function passNull(int $i = null)
{ /* … */ }
passNull(null);

다행히도 유형 속성은 이러한 혼란스러운 동작을 허용하지 않습니다.

또한 개체나 클래스 유형에는 기본값을 가질 수 없다는 점에 유의하세요. 기본값을 설정하려면 생성자를 사용해야 합니다.

입력된 값을 초기화하는 확실한 장소는 물론 생성자입니다.

class Foo{
    private int $a;
    public function __construct(int $a)
    {
        $this->a = $a;
    }
}

하지만 앞서 언급한 내용도 기억하세요. 생성자 외부에서 초기화되지 않은 속성을 작성하는 것은 유효합니다. 속성에서 아무것도 읽지 않는 한 초기화되지 않은 검사는 수행되지 않습니다.

#TYPES OF TYPES

그렇다면 정확히 무엇을 입력할 수 있고 어떻게 입력할 수 있는지 이미 언급한 대로 입력된 속성은 클래스 내에서만 작동하며 앞에는 액세스 한정자나 var 키워드가 필요합니다.

사용 가능한 유형은 void 및 callable을 제외한 거의 모든 유형을 사용할 수 있습니다.

void는 값이 없음을 의미하므로 입력된 값에 사용하지 않는 것이 합리적입니다. 호출 가능은 약간 다릅니다.

Visible, "callable"은 다음과 같이 작성할 수 있습니다:

하지만 앞서 언급한 내용도 기억하세요. 생성자 외부에서 초기화되지 않은 속성을 작성하는 것은 유효합니다. 속성에서 아무것도 읽지 않는 한 초기화되지 않은 검사는 수행되지 않습니다.

참고로, PHP의 "호출 가능"은 다음과 같이 작성할 수 있습니다:

$callable = [$this, 'method'];

다음과 같은 (잘못된) 코드가 있다고 가정해 보겠습니다:

class Foo
{
    public callable $callable;
    
    public function __construct(callable $callable)
    { /* … */ }
}
class Bar
{
    public Foo $foo;
    
    public function __construct()
    {
        $this->foo = new Foo([$this, 'method'])
    }
    
    private function method()
    { /* … */ }
}
$bar = new Bar;
($bar->foo->callable)();

이 경우 $callable은 비공개 Bar:: 메서드를 참조하지만 사용됩니다. Foo 호출의 맥락에서. 이 문제로 인해 호출 가능 지원을 추가하지 않기로 결정되었습니다.

Closure는 유효한 유형이고 그것이 생성된 $this 컨텍스트를 기억할 것이기 때문에 이것은 큰 문제가 아닙니다.

그런데 사용 가능한 모든 유형의 목록은 다음과 같습니다.

● bool

● int

● float

● string

● array

● iterable

● object

● ?

● self & parent

● 클래스 및 인터페이스

# 강제 및 엄격한 타이핑

PHP는 우리가 좋아하고 싫어하는 동적 언어이며 가능할 때마다 유형을 캐스팅합니다. 정수가 필요한 문자열을 전달한다고 가정하면 PHP는 자동으로 문자열을 변환하려고 시도합니다.

function coerce(int $i)
{ /* … */ }
coerce('1'); // 1

동일한 원칙이 유형 속성에도 적용됩니다.

아래 코드는 유효하며 "1"을 1로 변환합니다.

class Bar
{
    public int $i;
}
$bar = new Bar;
$bar->i = '1'; // 1

이 동작이 마음에 들지 않으면 엄격한 타이핑을 선언하여 비활성화할 수 있습니다.

declare(strict_types=1);
$bar = new Bar;
$bar->i = '1'; // 1
Fatal error: Uncaught TypeError: 
Typed property Bar::$i must be int, string used

#Type Differences and Inheritance

PHP 7.4에서 향상된 유형 차이가 도입되었음에도 불구하고 유형 속성은 변경되지 않습니다.

이는 다음이 유효하지 않음을 의미합니다.

class A {}
class B extends A {}
class Foo
{
    public A $prop;
}
class Bar extends Foo
{
    public B $prop;
}
Fatal error: Type of Bar::$prop must be A (as in class Foo)

위의 예가 중요하지 않은 경우 다음을 살펴봐야 합니다.

class Foo
{
    public self $prop;
}
class Bar extends Foo
{
    public self $prop;
}

뒤에서 PHP는 실행하기 전에 참조하는 구체적인 클래스로 self를 대체합니다. 코드.

这意味着在本例中会抛出相同的错误。处理它的唯一方法,是执行以下操作:

class Foo
{
    public Foo $prop;
}
class Bar extends Foo
{
    public Foo $prop;
}

说到继承,您可能会发现很难找到任何好的用例来覆盖继承属性的类型。

虽然我同意这种观点,但值得注意的是,可以更改继承属性的类型,但前提是访问修饰符也从private更改为protected或public。

以下代码有效:

class Foo{
    private int $prop;
}
class Bar extends Foo
{
    public string $prop;
}

但是,不允许将类型从可为空的类型更改为不可为空或反向的类型。

class Foo
{
    public int $a;
    public ?int $b;
}
class Bar extends Foo
{
    public ?int $a;
    public int $b;
}
Fatal error: Type of Bar::$a must be int (as in class Foo)

翻译:https://stitcher.io/blog/typed-properties-in-php-74

위 내용은 PHP 7.4의 유형화된 속성의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.