hack形狀介紹

2018-11-01 17:33 更新

一個形狀的一組由零個或多個數據字段放在一起作為一個整體;它是一個數組的鍵是由Hack typechecker跟蹤。

例如:

<?hh 
shape ('x'  =>  int , 'y'  =>  int )

形狀的定義包含一組有序的字段,每個字段都有一個名稱和一個類型。在上述情況下,形狀由兩個int字段組成,分別是名稱'x'和名稱'y'。

<?hh

namespace Hack\UserDocumentation\Shapes\Introduction\Examples\Intro;

type Point = shape('x' => int, 'y' => int);

class C1 {
  private Point $origin;
  private function __construct(int $x = 0, int $y = 0) {
    $this->origin = shape('x' => $x, 'y' => $y);
  }
}

function distance_between_2_Points(Point $p1, Point $p2): float {
  // access shape info via keys in the shape map, in this case `x` and `y`
  $dx = $p1['x'] - $p2['x'];
  $dy = $p1['y'] - $p2['y'];
  return sqrt($dx*$dx + $dy*$dy);
}

function run(): void {
  $p1 = shape('x' => 4, 'y' => 6);
  $p2 = shape('x' => 9, 'y' => 2);
  var_dump(distance_between_2_Points($p1, $p2));
}

run();

Output

float(6.4031242374328)

雖然我們可以直接使用形狀類型,但是通常創(chuàng)建別名(例如Point上面的名稱)是方便的,而是使用它。

訪問字段

使用其名稱作為在對應形狀類型的形狀上操作的下標表達式中的鍵來訪問形狀中的字段。例如:

字段的名稱可以用兩種可能的形式之一寫成:

  • 單引號(如上例所示)
  • 類型string或類的常數int

請注意,整數文字不能直接用作字段名稱。

給定形狀定義中的所有字段的名稱必須是不同的,并且具有相同的形式。

所有非可變字段都是必需的

例如,當從函數返回形狀時,必須考慮所有字段; 否則Hack typechecker會引發(fā)錯誤。

<?hh

namespace Hack\UserDocumentation\Shapes\Introduction\Examples\Fields;

type user = shape('id' => int, 'name' => string);

class UserClass {
  public static function create_user(int $id, string $name): user {
    $user = shape();
    $user['id'] = $id;
    return $user;
  }
}

function run(): void {
  var_dump(UserClass::create_user(1, 'James'));
}

run();

Output

array(1) {
  ["id"]=>
  int(1)
}

在上面的例子中,我們忘記設置該形狀的名稱字段。請注意,HHVM仍將運行代碼,因為它只是覆蓋在下面的數組。

可空字段是可選的

typechecker將可選項和可空值混合。shape('name' => ?string)將同時匹配shape('name' => null)和shape()。因此,如果省略一個可空的字段,那么typechecker就不會引起錯誤。但是,OutOfBoundsException如果您嘗試讀取省略的字段,則運行時將會引發(fā)。

類常數(Class Constants

類常數可用于Shapes。

<?hh

namespace Hack\UserDocumentation\Shapes\Introduction\Examples\ClassConstants;

class C2 {
  const string KEYA = 'x';
  const string KEYB = 'y';
  const int KEYX = 10;
  const int KEYY = 23;
}

type PointS = shape(C2::KEYA => int, C2::KEYB => int);
type PointI = shape(C2::KEYX => int, C2::KEYY => int);

function print_pointS(PointS $p): void {
  var_dump($p);
}

function print_pointI(PointI $p): void {
  var_dump($p);
}

function run(): void {
  print_pointI(shape(C2::KEYX => -1, C2::KEYY => 2));
  print_pointS(shape(C2::KEYA => -1, C2::KEYB => 2));
}

run();

Output

array(2) {
  [10]=>
  int(-1)
  [23]=>
  int(2)
}
array(2) {
  ["x"]=>
  int(-1)
  ["y"]=>
  int(2)
}

在上面我們例子中的整數類常量的情況下,通過任意選擇,x坐標被存儲在具有鍵10的元素中,而y坐標被存儲在具有鍵23的元素中。

沒有類型別名的形狀

形狀不必具有與其相關聯的類型別名。這是一個在所有地方使用文字形狀語法的例子。

<?hh

namespace Hack\UserDocumentation\Shapes\Intro\Examples\Anonymous;

class C {

  public function __construct(
    private shape('real' => float, 'imag' => float) $prop) {}

  public function setProp(shape('real' => float, 'imag' => float) $val): void {
    $this->prop = shape('real' => $val['real'], 'imag' => $val['imag']);
  }

  public function getProp(): shape('real' => float, 'imag' => float) {
    return $this->prop;
  }
}

function main(): void {
  $c = new C(shape('real' => -2.5, 'imag' => 1.3));
  var_dump($c);
  $c->setProp(shape('real' => 2.0, 'imag' => 99.3));
  var_dump($c->getProp());
}

main();

Output

object(Hack\UserDocumentation\Shapes\Intro\Examples\Anonymous\C)#1 (1) {
  ["prop":"Hack\UserDocumentation\Shapes\Intro\Examples\Anonymous\C":private]=>
  array(2) {
    ["real"]=>
    float(-2.5)
    ["imag"]=>
    float(1.3)
  }
}
array(2) {
  ["real"]=>
  float(2)
  ["imag"]=>
  float(99.3)
}

注意事項

形狀是數組; 即呼叫is_array()將返回true。但是,您可以使用不能使用形狀的數組執(zhí)行一些操作。

  • 您不能用未知鍵讀取或寫入。例如,$shape[$var]無效。鍵必須是字符串字面值或類常量。
  • 您不能[]在形狀上使用數組追加運算符。
  • 你不能foreach 形狀,因為它不實現TraversableContainer


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

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號