ホームページ  >  記事  >  バックエンド開発  >  PHP 7.4 の型付きプロパティ

PHP 7.4 の型付きプロパティ

藏色散人
藏色散人オリジナル
2019-11-30 13:32:114138ブラウズ

Type 属性は 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 に型がない場合、その値は null になります。ただし、型は null になる可能性があるため、null 型のプロパティが設定されたのか、単に忘れられていたのかを知る方法はありません。そのため「初期化されていない」が追加されました。

未初期化について覚えておくべき 4 つの事項:

##● 初期化されていないプロパティは読み取ることができないため、読み取りを行うと致命的なエラーが発生します。

# プロパティにアクセスするときに初期化されていないステータスがチェックされるため、型が null 許容でない場合でも、初期化されていないプロパティを持つオブジェクトを作成することができます。

# 最初に初期化されていないプロパティに書き込んでから、それを読み取ることができます。

# 型付きプロパティで unset を使用すると初期化されなくなりますが、型なしプロパティを設定解除すると null になります。

特に、次のコードは有効であることに注意してください。このコードでは、初期化されていない、Null 不可のプロパティがオブジェクトの構築後に設定されています。

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

ただし、初期化されていない、Null 不可なプロパティは、プロパティ値を読み取るときにチェックされます。状態は初期化されますが、プロパティ値を書き込むときに型検証が行われます。これは、無効な型がプロパティ値として扱われないようにできることを意味します。

#デフォルト値とコンストラクター

型指定された値を初期化する方法を詳しく見てみましょう。スカラー型の場合は、デフォルト値を指定できます。

class Foo
{
    public int $a;
}
$foo = new Foo;
$foo->a = 1;
型が実際に空の場合、デフォルト値として null のみを使用できることに注意してください。これは明らかなように思えますが、パラメーターのデフォルトには古い動作があり、次のことが可能でした。
class Foo
{
    public int $bar = 4;
    
    public ?string $baz = null;
    
    public array $list = [1, 2, 3];
}

幸いなことに、type 属性ではこのような混乱を招く動作は許可されません。

オブジェクト型またはクラス型にはデフォルト値を設定できないことにも注意してください。コンストラクターを使用してデフォルト値を設定する必要があります。

型指定された値を初期化する明白な場所は、もちろんコンストラクターです:

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

ただし、前に述べたことも覚えておいてください。コンストラクターの外で初期化されていないプロパティを記述することは有効です。プロパティから何も読み取られない限り、初期化されていないチェックは実行されません。

#タイプのタイプ

それでは、正確に何を、どのように入力できるのでしょうか? 型付きプロパティは (現時点では) クラス内でのみ有効であるとすでに述べました。アクセス修飾子または var キーワードがそれらの前に置かれます。

使用可能な型は、void と callable を除くほぼすべての型が使用できます。

void は値がないことを意味するため、型付きの値には使用できないのは当然です。 callable は少し異なります。

PHP の「呼び出し可能」は次のように記述できることがわかります。

ただし、前に述べたことも覚えておいてください。コンストラクターの外で初期化されていないプロパティを記述することは有効です。プロパティから何も読み取られない限り、初期化されていないチェックは実行されません。

ほら、PHP の「呼び出し可能」は次のように記述できます:

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

次の (無効な) コードがあるとします。

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

この例では、$callableプライベート Bar::method を参照しますが、Foo のコンテキストで呼び出されます。この問題のため、呼び出し可能なサポートを追加しないことが決定されました。

ただし、Closure は有効な型であり、それが構築された $this コンテキストを記憶しているため、これは大したことではありません。

ちなみに、使用可能なすべての型のリストは次のとおりです。

##● bool

##● int

##● float

##●文字列

##● 配列

##● iterable

##● object

##● ? (null 可能)

##● self &parent

● クラスとインターフェイス

# 強制型付けと厳密型付け

PHP は、私たちが好きでも嫌いでもある動的言語であり、可能な限り型をキャストします。整数が期待される場所に文字列を渡すと、PHP は文字列を自動的に変換しようとします。

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)();

同じ原則が型属性にも当てはまります。

以下のコードは有効で、「1」を 1 に変換します。

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

この動作が気に入らない場合は、厳密な型指定を宣言することで無効にすることができます。

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

#型の違いと継承

偶数PHP 7.4 では型の違いが改善されましたが、型のプロパティは変更されていません。

これは、次の内容が無効であることを意味します:

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

上記の例が重要ではないと思われる場合は、以下を参照してください:

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)

コードを実行する前に、 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 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。