国产chinesehdxxxx野外,国产av无码专区亚洲av琪琪,播放男人添女人下边视频,成人国产精品一区二区免费看,chinese丰满人妻videos

hack類(lèi)型別名:Opaque

2018-11-21 10:18 更新

一個(gè)不透明類(lèi)型別名使用創(chuàng)建的newtype。與透明類(lèi)型別名不同,小心組織源代碼,編譯器可以確保通用代碼不能直接訪(fǎng)問(wèn)不透明別名的基礎(chǔ)類(lèi)型。

沒(méi)有類(lèi)型約束的別名

每個(gè)不透明的別名類(lèi)型都不同于其基礎(chǔ)類(lèi)型,也不同于其他任何類(lèi)型的別名。只有包含opaque類(lèi)型別名定義的文件中的源代碼被允許訪(fǎng)問(wèn)底層的實(shí)現(xiàn)。

考慮一個(gè)文件,point.inc.php它包含一個(gè)2D點(diǎn)類(lèi)型和一些函數(shù)原語(yǔ)的不透明的別名定義:

<?hh

namespace Hack\UserDocumentation\TypeAliases\Opaque\Examples\AliasNoConstraint;

// point.php - Point implementation file

newtype Point = (int, int);

function createPoint(int $x, int $y): Point {
  return tuple($x, $y);
}

function setX(Point $p, int $x): Point {
  $p[0] = $x;
  return $p;
}

function setY(Point $p, int $y): Point {
  $p[1] = $y;
  return $p;
}

function getX(Point $p): int {
  return $p[0];
}

function getY(Point $p): int {
  return $p[1];
}

只有那些需要知道Point底層結(jié)構(gòu)的函數(shù)應(yīng)該在上面的Point實(shí)現(xiàn)文件中定義。所有支持該Point類(lèi)型的通用函數(shù)都可以駐留在PointFunctions.php中,如下所示:

<?hh

namespace Hack\UserDocumentation\TypeAliases\Opaque\Examples\AliasNoConstraint;

// point-functions.php - Point's supporting functions

function distance_between_2_Points(Point $p1, Point $p2): float {
  $dx = getX($p1) - getX($p2);
  $dy = getY($p1) - getY($p2);
  return sqrt($dx*$dx + $dy*$dy);
}

這里是一些創(chuàng)建和使用點(diǎn)的代碼:

<?hh

namespace Hack\UserDocumentation\TypeAliases\Opaque\Examples\AliasNoConstraint;

// test-point.php - User code that tests type Point

function run(): void {
  $p1 = createPoint(5, 3);
  var_dump($p1);
  $p2 = createPoint(9, -5);
  var_dump($p2);
  $dist = distance_between_2_Points($p1, $p2);
  echo "distance between points is " . $dist ."\n";
  // But we cannot pass a tuple of two ints since they are not a Point
  // This will give a Hack typechecker error
  $will_not_type_check = distance_between_2_Points(tuple(2, 3), tuple(3, 4));
  // However, the code will still run in HHVM
  echo "distance between points is " . $will_not_type_check ."\n";
}

run();

/*

Here is the type error for $will_not_type_check

test-point.php:18:52,62: Invalid argument (Typing[4110])
  point-functions.inc.php:9:36,40:
     This is an object of type
     Hack\UserDocumentation\TypeAliases\Opaque\Examples\AliasNoConstraint\Point
  test-point.php:18:52,62: It is incompatible with a tuple
test-point.php:18:65,75: Invalid argument (Typing[4110])
  point-functions.inc.php:9:47,51:
     This is an object of type
     Hack\UserDocumentation\TypeAliases\Opaque\Examples\AliasNoConstraint\Point
  test-point.php:18:65,75: It is incompatible with a tuple

*/

Output

array(2) {
  [0]=>
  int(5)
  [1]=>
  int(3)
}
array(2) {
  [0]=>
  int(9)
  [1]=>
  int(-5)
}
distance between points is 8.9442719099992
distance between points is 1.4142135623731

與別名定義相同的文件,功能createPoint和朋友有---和需要---直接訪(fǎng)問(wèn)任何點(diǎn)的元組中的整數(shù)字段。但是,任何其他文件不。

類(lèi)型約束的別名

考慮一個(gè)包含以下不透明類(lèi)型定義的文件:

<?hh 
newtype  Counter  =  int ;

任何包含這個(gè)文件的文件都不知道a Counter是一個(gè)整數(shù),所以包含文件不能在該類(lèi)型上執(zhí)行任何類(lèi)似整數(shù)的操作。這是一個(gè)主要的限制,因?yàn)槌橄箢?lèi)型的所謂的精心選擇的名稱(chēng)Counter,表明其價(jià)值可能增加和/或減少。我們可以通過(guò)向別名的定義添加一個(gè)類(lèi)型約束來(lái)“解決”這個(gè)問(wèn)題,如下所示:

<?hh
newtype Counter as int = int;

類(lèi)型約束的存在允許將不透明類(lèi)型視為具有由類(lèi)型約束指定的類(lèi)型,這將刪除一些別名的不透明。盡管約束的存在允許將別名類(lèi)型隱式轉(zhuǎn)換為約束類(lèi)型,但是沒(méi)有相反的方向定義轉(zhuǎn)換。在這個(gè)例子中,這意味著a Counter可以被隱式地轉(zhuǎn)換成一個(gè)int,而不是相反的。下面的例子會(huì)因?yàn)檫@個(gè)原因而無(wú)法檢查:

<?hh
// Assume this code is in a different file than where the Counter type is
// defined.
class A {
  public Counter $c;

  public function __construct() {
    // This is prohibited, as there is no implicit conversion from int 
    // (the type of 0) to Counter   
    $this->c = 0;
  }
} 

類(lèi)型約束必須是被別名的類(lèi)型的子類(lèi)型。

在下面的例子中,Point有一個(gè)約束(int, int); 因此我們可以通過(guò)Point任何方法期待(int, int)...但反之亦然!

<?hh

namespace Hack\UserDocumentation\TypeAliases\Opaque\Examples\AliasConstraint;

// point-constraint.inc.php - Point implementation file

newtype Point as (int, int) = (int, int);

function createPoint(int $x, int $y): Point {
  return tuple($x, $y);
}

function setX(Point $p, int $x): Point {
  $p[0] = $x;
  return $p;
}

function setY(Point $p, int $y): Point {
  $p[1] = $y;
  return $p;
}

function getX(Point $p): int {
  return $p[0];
}

function getY(Point $p): int {
  return $p[1];
}

上面的兩個(gè)例子激發(fā)了幾個(gè)用例,在這樣的不透明類(lèi)型別名中戳洞。

在這個(gè)Counter例子中,我們可能對(duì)a的值Counter以及它的維護(hù)方式有額外的限制,因此需要不透明度來(lái)確保合適的不變量得到尊重。這意味著我們不能讓任何人int成為一個(gè)Counter。但是換個(gè)方式就好了; 做一個(gè)Counter有道理的數(shù)學(xué)。

對(duì)于Point例如,它可能看起來(lái)像我們?cè)诤艽蟪潭壬洗蚱屏顺橄驪oint,而事實(shí)上我們。你可能不想編寫(xiě)看起來(lái)像這樣的新代碼。但是,在轉(zhuǎn)換現(xiàn)有的非類(lèi)型代碼時(shí),它可能非常有用。我們可以引入一個(gè)新的Point不透明別名,但是有一個(gè)類(lèi)型限制,用于向后兼容。任何新的代碼都會(huì)使用這個(gè)Point類(lèi)型,從而受到Point抽象及其不變性的影響。(int, int)如果需要,現(xiàn)有的代碼可以繼續(xù)直接在元組上工作。但是,如果不Point經(jīng)過(guò)抽象,代碼就不能轉(zhuǎn)換回來(lái),所以抽象不能被破壞。一旦所有的代碼都被轉(zhuǎn)換,別名上的約束可以被刪除,并且可以是完全不透明的。

以上內(nèi)容是否對(duì)您有幫助:
在線(xiàn)筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)