hack形狀子類(lèi)型化

2018-11-02 16:22 更新

考慮具有公共初始字段序列的兩種形狀類(lèi)型。例如:

enum Bank: int {
  DEPOSIT = 1;
  // ...
}

type Transaction = shape('trtype' => Bank);
type Deposit = shape('trtype' => Bank, 'toaccnum' => int, 'amount' => float);

具有較大字段集的形狀類(lèi)型Deposit是具有較小字段集的子類(lèi)型Transaction。前者有后者的所有領(lǐng)域,所以前者的價(jià)值可以用來(lái)代替后者。例如,您現(xiàn)在可以編寫(xiě)一個(gè)對(duì)所有具有稱(chēng)為“ 'trtype'類(lèi)型Bank” 字段的形狀進(jìn)行操作的函數(shù)。例如:

<?hh

namespace Hack\UserDocumentation\Shapes\Examples\Subtyping\Subtype;

enum Bank: int {
  INVALID = 0;
  DEPOSIT = 1;
  WITHDRAWAL = 2;
  TRANSFER = 3;
}

type Transaction = shape('trtype' => Bank);
type Deposit = shape('trtype' => Bank, 'toaccnum' => int, 'amount' => float);
type Withdrawal = shape('trtype' => Bank, 'fromaccnum' => int,
                        'amount' => float);
type Transfer = shape('trtype' => Bank, 'fromaccnum' => int,
                      'toaccnum' => int, 'amount' => float);

function processTransaction(Transaction $t): void {
  var_dump($t);

  $a = Shapes::toArray($t);
  var_dump(count($a), $a);

  $v = Shapes::idx($t, 'trtype', Bank::INVALID);  // checker accepts this
  var_dump($v);

  $v = Shapes::keyExists($t, 'trtype');   // checker accepts this
  var_dump($v);

  Shapes::removeKey($t, 'xyz');   // checker accepts this
  var_dump($t);

  // checker complains Invalid argument (Typing[4140])
  $v = Shapes::idx($t, 'amount', -999.0); // The field 'amount' is missing
  var_dump($v);

  // checker complains Invalid argument (Typing[4140])
  $v = Shapes::keyExists($t, 'amount'); // The field 'amount' is missing
  var_dump($v);

  // checker is fine here because we used removeKey above
  $v = Shapes::keyExists($t, 'xyz'); // The field 'xyz' is missing
  var_dump($v);

  switch ($t['trtype']) {
    case Bank::TRANSFER:
      echo "Transfer: " . $t['amount'] . " from Account " . $t['fromaccnum'] .
           " to Account " . $t['toaccnum'] . "\n";
      break;
    case Bank::DEPOSIT:
      // The field amount is undefined (Typing[4108])
      // The field toaccnum is undefined (Typing[4108])
      echo "Deposit: " . $t['amount'] . " to Account " . $t['toaccnum'] . "\n";
      break;
    case Bank::WITHDRAWAL:
      echo "Withdrawal: " . $t['amount'] . " from Account " .
           $t['fromaccnum'] . "\n";
      break;
    default:
      break;
  }
}

function main(): void {
  processTransaction(shape('trtype' => Bank::DEPOSIT, 'toaccnum' => 23456,
                           'amount' => 100.00));
  processTransaction(shape('trtype' => Bank::WITHDRAWAL, 'fromaccnum' => 3157,
                           'amount' => 100.00));
  processTransaction(shape('trtype' => Bank::TRANSFER, 'fromaccnum' => 23456,
                           'toaccnum' => 3157, 'amount' => 100.00));
}

main();

Output

array(3) {
  ["trtype"]=>
  int(1)
  ["toaccnum"]=>
  int(23456)
  ["amount"]=>
  float(100)
}
int(3)
array(3) {
  ["trtype"]=>
  int(1)
  ["toaccnum"]=>
  int(23456)
  ["amount"]=>
  float(100)
}
int(1)
bool(true)
array(3) {
  ["trtype"]=>
  int(1)
  ["toaccnum"]=>
  int(23456)
  ["amount"]=>
  float(100)
}
float(100)
bool(true)
bool(false)
Deposit: 100 to Account 23456
array(3) {
  ["trtype"]=>
  int(2)
  ["fromaccnum"]=>
  int(3157)
  ["amount"]=>
  float(100)
}
int(3)
array(3) {
  ["trtype"]=>
  int(2)
  ["fromaccnum"]=>
  int(3157)
  ["amount"]=>
  float(100)
}
int(2)
bool(true)
array(3) {
  ["trtype"]=>
  int(2)
  ["fromaccnum"]=>
  int(3157)
  ["amount"]=>
  float(100)
}
float(100)
bool(true)
bool(false)
Withdrawal: 100 from Account 3157
array(4) {
  ["trtype"]=>
  int(3)
  ["fromaccnum"]=>
  int(23456)
  ["toaccnum"]=>
  int(3157)
  ["amount"]=>
  float(100)
}
int(4)
array(4) {
  ["trtype"]=>
  int(3)
  ["fromaccnum"]=>
  int(23456)
  ["toaccnum"]=>
  int(3157)
  ["amount"]=>
  float(100)
}
int(3)
bool(true)
array(4) {
  ["trtype"]=>
  int(3)
  ["fromaccnum"]=>
  int(23456)
  ["toaccnum"]=>
  int(3157)
  ["amount"]=>
  float(100)
}
float(100)
bool(true)
bool(false)
Transfer: 100 from Account 23456 to Account 3157

但是有一個(gè)重要的警告。內(nèi)部功能processTransaction唯一的領(lǐng)域是你可以訪(fǎng)問(wèn)$t'trtype'。即使您使用交換機(jī)case Bank::DEPOSIT:(例如)來(lái)確定事務(wù)的實(shí)際類(lèi)型也是如此。

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

掃描二維碼

下載編程獅App

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

編程獅公眾號(hào)