hack泛型:Erasure

2018-11-16 10:17 更新

通過泛型參數(shù)化類型的能力為開發(fā)人員和代碼用戶提供了強大的可讀性優(yōu)勢。它還提供了typechecker必要的信息,以確保您是代碼的方式。例如,將Box<int>函數(shù)作為參數(shù)類型清楚地顯示了Box應包含的類型,類型檢查器也可以使用這些信息。

但是,除了異步函數(shù)的返回類型(Awaitable),對泛型的支持只能通過類型注釋在類型分類器上進行 ; 它們在運行時不存在。泛型類型參數(shù)和參數(shù),并在執(zhí)行之前剝離(即擦除)。使用我們Box上面的例子,這意味著Box<int>真正Box在運行時,HHVM將允許你傳遞非int Box函數(shù)。

<?hh

namespace Hack\UserDocumentation\Generics\Erasure\Examples\TypeErasure;

class Box<T> {
  private T $x;
  public function __construct(T $x) {
    $this->x = $x;
  }
  public function get(): T {
    return $this->x;
  }
}

function foo(Box<int> $b): void {
  var_dump($b);
}

function run(): void {
  $b = new Box(4);
  $c = new Box("hi");
  foo($b);
  foo($c);
}

run();

/*****
* Typechecker error:
*
* File "type-erasure.php", line 23, characters 7-8:
* Invalid argument (Typing[4110])
* File "type-erasure.php", line 15, characters 18-20:
* This is an int
* File "type-erasure.php", line 21, characters 16-19:
* It is incompatible with a string
* File "type-erasure.php", line 15, characters 18-20:
* Considering that this type argument is invariant with respect to Hack\UserDocumentation\Generics\Erasure\Examples\TypeErasure\Box
****/

Output

object(Hack\UserDocumentation\Generics\Erasure\Examples\TypeErasure\Box)#1 (1) {
  ["x":"Hack\UserDocumentation\Generics\Erasure\Examples\TypeErasure\Box":private]=>
  int(4)
}
object(Hack\UserDocumentation\Generics\Erasure\Examples\TypeErasure\Box)#2 (1) {
  ["x":"Hack\UserDocumentation\Generics\Erasure\Examples\TypeErasure\Box":private]=>
  string(2) "hi"
}

雖然通用參數(shù)化確實是一個很大的好處,但是由于運行時的類型擦除,您需要注意一些限制。類型參數(shù)T不能在以下情況下使用:

  • 使用new(例如new T())創(chuàng)建實例。
  • Casting(例如(T) $value)。
  • 在一個類的范圍內,例如T::aStaticMethod()。
  • 作為instanceof核查的正面。
  • 作為靜態(tài)屬性的類型。
  • 作為catch塊中的異常的類型(例如,catch (T $exception))。

對于實例化,類范圍和instanceof用法的可能替代,Hack提供了一個叫做Classname<T>擴展PHP表示的構造Foo::class。

以上內容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號