hysryt / wiki

https://hysryt.github.io/wiki/
0 stars 0 forks source link

PHP8.1 #191

Open hysryt opened 2 years ago

hysryt commented 2 years ago

https://www.php.net/archive/2021.php#2021-11-25-1 https://www.php.net/releases/8.1/en.php https://www.php.net/manual/en/migration81.php

hysryt commented 2 years ago

列挙型(Enumerations)

https://www.php.net/manual/ja/language.enumerations.php

enum Status
{
    case Draft;
    case Published;
    case Archived;
}
function acceptStatus(Status $status) {...}

PHPでは列挙型はクラスであり、定義されるcaseはそれぞれインスタンス。

$a = Suit::Spades;
$b = Suit::Spades;

$a === $b; // true

$a instanceof Suit;  // true

列挙型はメソッドを持つことができる。 スタティックメソッドを持つこともできる。 インターフェースを実装することもできる。 定数を持つこともできる。 トレイトを使う(use)することもできるが、トレイトがプロパティを持たない場合のみ。

コンストラクタやデストラクタは無い。 列挙型を継承することはできない。 プロパティは持てない。 clone できない。

列挙型は内部的に UnitEnum インターフェースを実装している。

hysryt commented 2 years ago

値に依存した列挙型(Backed Enumerations)

各caseがスカラー値を持つ列挙型

enum Suit: string
{
    case Hearts = 'H';
    case Diamonds = 'D';
    case Clubs = 'C';
    case Spades = 'S';
}

Backed Enum の各ケースは Backed Case と呼ばれる。

case が持つ値は整数か文字列のみで、同じ列挙型の中にはいずれか一方の型しか持てない。 値にアクセスするには Suit::Hearts->value のようにする。

hysryt commented 2 years ago

readonly 修飾子

https://wiki.php.net/rfc/readonly_properties_v2

読み込み専用のプロパティ。

class BlogData
{
    public readonly Status $status;

    public function __construct(Status $status)
    {
        $this->status = $status;
    }
}

一度値が割り当てられた後は読み込みしかできない。 プロパティをパブリックかつ変更不可にできる。

型付きのプロパティにしか使用できない。 型をつけたくない場合は mixed 型を使用する。

デフォルト値を設定できない。 コンストラクタでのデフォルト値設定は大丈夫。

hysryt commented 2 years ago

第一級Callable

https://wiki.php.net/rfc/first_class_callable_syntax https://www.php.net/manual/en/migration81.new-features.php#migration81.new-features.core.callable-syntax

$foo = [$this, 'foo'];
↓
$foo = $this->foo(...);

$fn = Closure::fromCallable('strlen');
↓
$fn = strlen(...);

... は何かを省略しているわけではなくてそういう構文。 クロージャを直感的に作ることができるようになった。

クロージャが作成された時点のスコープを尊重する。 例えば $foo = [$this, 'foo']; とした場合、foo がプライベートな場合は外から呼び出しができない。 Closure::fromCallable([$this, 'privateMethod']); とかけば外から呼び出せるが少し長い。 $this->foo(...) とすれば外から呼び出せて短く書ける。

hysryt commented 2 years ago

関数のデフォルト引数でnew

https://wiki.php.net/rfc/new_in_initializers

class Service
{
    private Logger $logger;

    public function __construct(
        Logger $logger = new NullLogger(),
    ) {
        $this->logger = $logger;
    }
}

デフォルト引数でnewを使えるようになった。 他にもアトリビュートの引数、static変数の初期化子、グローバル定数の初期化子でも使えるようになった。

static $x = new Foo;

const C = new Foo;

function test($param = new Foo) {}

#[AnAttribute(new Foo)]
class Test {
    public function __construct(
        public $prop = new Foo,
    ) {}
}

クラスのstatic変数や定数に指定した場合、クラスが使用されたタイミングで new が実行される。

ネストしたアトリビュートが書けるようになった。

#[Assert\All(new Assert\NotNull, new Assert\Length(max: 6))]
hysryt commented 2 years ago

交差型(Intersection)

https://wiki.php.net/rfc/pure-intersection-types

function count_and_iterate(Iterator&Countable $value) {
    ...
}

複数の型制約を同時に満たすことを要求する際に使用する。 union型と混在して使用することはできない。

交差型に使用できるのかインターフェースかクラスのみ。

hysryt commented 2 years ago

never型

https://wiki.php.net/rfc/noreturn_type https://www.php.net/manual/en/language.types.declarations.php#language.types.declarations.never

関数が返らないことを表す戻り値。 関数は exit() で終了するか、例外が発生するか、無限ループになるかのいずれかとなる。 他の方と一緒にユニオン型にすることはできない。

他の全ての型のサブタイプであり、継承時に他の戻り値を置き換えることができる。 逆に never を他の方に置き換えることはできない。

関数内で return や yield は使えない。

never は引数やプロパティの型として使うことはできない。

hysryt commented 2 years ago

finalクラス定数

https://wiki.php.net/rfc/final_class_const

class Foo {
    final public const XX = "foo";
}

クラス定数に final をつけることで、サブクラスでオーバーライドできなくなる。

ちなみにインターフェースの定数はもともとオーバーライドできなかった。 ただし、一度実装(implements)してから継承するとオーバーライドできてしまっていた。 PHP8.1以降ではインターフェースの定数もデフォルトでオーバーライドができるようになり、 finalをつけるとクラスと同様にできなくなるように変更となった。

hysryt commented 2 years ago

8進数のプレフィックス

https://wiki.php.net/rfc/explicit_octal_notation https://www.php.net/manual/en/migration81.new-features.php#migration81.new-features.core.octal-literal-prefix

0o16 === 16; // false
0o16 === 14; // true

8進数のプレフィックスとして 0o が使えるようになった。 今までは 0 で始まる数値が8進数として扱われていたが、わかりづらかった。

octdec()base_convert() ではすでにこのプレフィックスに対応していたらしい。

hysryt commented 2 years ago

Fiber

https://www.php.net/manual/en/class.fiber.php

プリミティブ? 協調的な並行処理が行える機能。 Fiberはそれぞれが独自のコールスタックを持ち、一時停止や再開が可能。 並行処理を行うには別途イベントループが必要?

Fiberについて記述された記事の翻訳 https://github.com/hysryt/translation/issues/6 https://github.com/hysryt/translation/issues/7

コルーチンやグリーンスレッドというもののPHPでの実装と考えるのが良さそう? Fiberを使えば複数の処理をそれぞれ少しずつ進めるということができる?

※イベントループ イベントの監視と処理を繰り返す無限ループ ここではFiberの状態を監視するループのこと?

hysryt commented 2 years ago

連想配列のアンパック

$arrayA = ['a' => 1];
$arrayB = ['b' => 2];

$result = ['a' => 0, ...$arrayA, ...$arrayB];

// ['a' => 1, 'b' => 2]

今まで配列で使えていたスプレッド演算子が連想配列でも使用できるようになった。

hysryt commented 2 years ago

array_is_list()

https://www.php.net/manual/en/function.array-is-list.php

指定した配列がリストであるかどうかを判定する。 配列のキーが 0 から count($array)-1 までの連続した数字で構成されている場合、その配列はリストとされる。

hysryt commented 2 years ago

$GLOBAL配列へのアクセスの制限

$GLOBALS 配列全体への書き込みアクセスはサポートされない。 たとえば、array_pop($GLOBALS)はエラー。