可空型別
可空型別主要用於參數型別宣告和函數傳回值宣告。
主要的兩種形式如下:
<?phpfunction answer(): ?int { return null; //ok}function answer(): ?int { return 42; // ok}function say(?string $msg) { if ($msg) { echo $msg; }}
從例子很容易理解,所指的就是透過 ? 的形式表示函數參數或傳回值的型別要為指定型別,要嘛為 null。
此方法也可用於介面函數的定義:
<?php interface Fooable { function foo(?Fooable $f);}
但有一個需要注意的地方:如果函數本身定義了參數類型並且沒有預設值,即使是可空的,也不能省略,否則會觸發錯誤。如下:
<?php function foo_nullable(?Bar $bar) {} foo_nullable(new Bar); // 可行foo_nullable(null); // 可行foo_nullable(); // 不可行
但是如果上述函數的參數定義為 ?Bar $bar = null 的形式,則第三種寫法也是可行的。因為= null 其實相當於 ? 的超集,對於可空型別的參數,可以設定 null 為預設值。
list 的方括號簡寫
我們知道在PHP5.4 之前只能通過 array() 來定義數組,5.4之後添加了 [] 的簡化寫法(省略了5個字符還是很實在的。
<?php // 5.4 之前$array = array(1, 2, 3);$array = array("a" => 1, "b" => 2, "c" => 3); // 5.4 及之后$array = [1, 2, 3];$array = ["a" => 1, "b" => 2, "c" => 3];
引申到另一個問題上,如果我們要把數組的值賦值給不同的變量,可以透過 list 來實現:
<?php list($a, $b, $c) = $array;
是否也可以透過 [] 的簡寫來實現呢?
<?php [$a, $b, $c] = $array;
以及下一個特性中會提到的 list 指定 key:
<?php ["a" => $a, "b" => $b, "c" => $c] = $array;
PHP7.1 實現了這個特性。但要注意的是:出現在左值的 [] 並不是陣列的簡寫,是list() 的簡寫。
但是並不僅僅如此,新的 list() 的實現並不僅僅可以出現在左值中,也能在 foreach 循環中使用:
<?php foreach ($points as ["x" => $x, "y" => $y]) { var_dump($x, $y);
不過因為實現的問題,list() 和[] 不能互相嵌套使用:
<?php // 不合法 list([$a, $b], [$c, $d]) = [[1, 2], [3, 4]]; // 不合法 [list($a, $b), list($c, $d)] = [[1, 2], [3, 4]]; // 合法 [[$a, $b], [$c, $d]] = [[1, 2], [3, 4]];
允許在list 中指定key
上文提到過,新的 list() 的實作中可以指定key:
<?php $array = ["a" => 1, "b" => 2, "c" => 3];["a" => $a, "b" => $b, "c" => $c] = $array;
這也相當於:
<?php $a = $array['a'];$b = $array['b'];$c = $array['c'];
和過去的差異在於以往的 list() 的實作相當於key 只能是 0, 1, 2, 3 的數位形式且無法調整順序。執行下列語句:
<?php list($a, $b) = [1 => '1', 2 => '2'];
會得到 PHP error: Undefined offset: 0... 的錯誤。
而新的實作則可以透過以下方式來調整賦值:
<?php list(1 => $a, 2 => $b) = [1 => '1', 2 => '2'];
不同於數組的是,list 並不支援混合形式的key,以下寫法會觸發解析錯誤:
<?php // Parse error: syntax error, ...list($unkeyed, "key" => $keyed) = $array;
更複雜的情況,list也支援複合形式的解析:
<?php $points = [ ["x" => 1, "y" => 2], ["x" => 2, "y" => 1]]; list(list("x" => $x1, "y" => $y1), list("x" => $x2, "y" => $y2)) = $points; $points = [ "first" => [1, 2], "second" => [2, 1]]; list("first" => list($x1, $y1), "second" => list($x2, $y2)) = $points;
以及循環中使用:
<?php $points = [ ["x" => 1, "y" => 2], ["x" => 2, "y" => 1]]; foreach ($points as list("x" => $x, "y" => $y)) { echo "Point at ($x, $y)", PHP_EOL;}
void 回傳型別
PHP7.0 增加了指定函數傳回型態的特性,但回傳型別卻不能指定為 void,7.1 的這個特性算是一個會傳回型別的特性,但是回傳型別卻不能指定為 void,7.1 的這個特性算是一個補充:
<?php function should_return_nothing(): void { return 1; // Fatal error: A void function must not return a value}
以下兩種情況都可以通過驗證:
<?php function lacks_return(): void { // valid} function returns_nothing(): void { return; // valid}
定義回傳類型為 void 的函數不能有回傳值,即使回傳 null 也不行:
<?php function returns_one(): void { return 1; // Fatal error: A void function must not return a value} function returns_null(): void { return null; // Fatal error: A void function must not return a value}
此外 void 也只適用於回傳類型於參數類型聲明,或會觸發錯誤:
<?php function foobar(void $foo) { // Fatal error: void cannot be used as a parameter type}
類函數中對於返回類型的聲明也不能被子類覆蓋,否則會觸發錯誤:
<?php class Foo{ public function bar(): void { } } class Foobar extends Foo{ public function bar(): array { // Fatal error: Declaration of Foobar::bar() must be compatible with Foo::bar(): void }}
類常數屬性設定
這個特性說起來比較簡單,就是現在類別中的常數支援使用 public、private 和 protected修飾了:
<?php class Token { // 常量默认为 public const PUBLIC_CONST = 0; // 可以自定义常量的可见范围 private const PRIVATE_CONST = 0; protected const PROTECTED_CONST = 0; public const PUBLIC_CONST_TWO = 0; // 多个常量同时声明只能有一个属性 private const FOO = 1, BAR = 2;}
此外,介面(interface)中的常數只能是 public 屬性:
<?php interface ICache { public const PUBLIC = 0; const IMPLICIT_PUBLIC = 1;}
為了應對變化,反射類別的實作也對應的豐富反射屬性:
<?php class testClass { const TEST_CONST = 'test'; } $obj = new ReflectionClass( "testClass" ); $const = $obj->getReflectionConstant( "TEST_CONST" ); $consts = $obj->getReflectionConstants();
為了應對變化,反射類別的實作也相應的豐富反射了一下,增加了 getReflectionConstant 和getReflectionConstants 兩個方法用於取得常數的額外屬性:
<?php try { // Some code... } catch (ExceptionType1 $e) { // 处理 ExceptionType1} catch (ExceptionType2 $e) { // 处理 ExceptionType2} catch (Exception $e) { // ...}
多條件catch
在以往的 try ... catch 語句中,每個條件判斷每個條件:
<?php try { // Some code...} catch (ExceptionType1 | ExceptionType2 $e) { // 对于 ExceptionType1 和 ExceptionType2 的处理} catch (Exception $e) { // ...}
rrreee
以上就是PHP 7.1 新特性一覽的內容,更多相關內容請關注PHP中文網(www.php. cn)!