hack高级规则

2018-10-04 12:29 更新

类型检查规则通常很简单(例如,不能传递string给期望的内容int)。然而,有一些规则有一些更高级的语义。

软类型提示

看看这个例子:

<?hh

namespace Hack\UserDocumentation\Types\AdvancedRules\Examples\SoftHint;

// HHVM will throw a warning instead of fatal if, for example, a bool is passed
// in
function foo(@int $x): bool {
  return $x < 5 ? true : false;
}

function call_foo(): void {
  foo(5);
  foo(false);
}

call_foo();

Output

Warning: Argument 1 to Hack\UserDocumentation\Types\AdvancedRules\Examples\SoftHint\foo() must be of type @int, bool given in /data/users/joelm/user-documentation/guides/hack/20-types/08-advanced-rules-examples/softhint.php.type-errors on line 9

前面的“@”是什么意思?这导致HHVM在传递的参数不匹配时触发警告(因此始终继续执行)而不是可捕获的致命错误。它用于允许您慢慢添加类型到您的代码。

软类型提示对类型检查器行为没有影响。如果类型不匹配,类型检查器仍然会抛出错误。

Superglobals

无论你目前在什么范围内,Superglobals都可以使用。

<?hh

namespace Hack\UserDocumentation\Types\AdvancedRules\Examples\SuperGlobals;

function get_superglobal(string $s): array<string> {
  // If you try to use a variable that doesn't exist (e.g., $_NOEXIST), the
  // typechecker will thrown an undefined variable error.
  switch ($s) {
    case '_GET':
      return $_GET;
      break;
    case '_ENV':
      return $_ENV;
      break;
    case '_SERVER':
      return $_SERVER;
      break;
    default: // not supporting anything else
      return array();
  }
}

function sg(string $s): array<string> {
  return get_superglobal($s);
}

var_dump(is_array(sg('_SERVER')));

Output

bool(true)

类型检查器知道内置超帧。

在Hack的严格模式下,superglobals不支持。所以你必须创建一些类似部分模式的功能,以从严格的模式文件中调用。

可以使用将PSR-7暴露给Hack 的存储库来实现使用superglobals的不完美但可行的替代方案。这个repo中的HHI文件给出了关于接口的Hack类型检查器信息。

可变参数

Hack支持可变参数

function foo(<any explicit arguments>, int ...$args) // $args is a list of int arguments

类型检查器将强制执行可变类型,但是对于性能,运行时不会。

<?hh

namespace Hack\UserDocumentation\Types\AdvancedRules\Examples\Variadic;

function foo(int ...$args): vec<int> {
  $ret = vec[];
  foreach ($args as $arg) {
    $ret[] = $arg;
  }
  return $ret;
}

function bar(): void {
  var_dump(foo(1, 2, 3, 4));
}

bar();

Output

vec(4){ 
  int(1)
  int(2)
  int(3)
  int(4)
}

Fallthrough

switch言论中无意的跌倒是一个常见的错误。黑客提供了一种抓住突破的方法,增加了一种告诉它这是有意的方法。

<?hh

namespace Hack\UserDocumentation\Types\AdvancedRules\Examples\Fallthrough;

function fallthrough(int $x): void {
  switch ($x) {
    case 1: echo "1"; break; // without the break, typechecker throws an error
    case 2: echo "2"; break;
    case 3: echo "3"; break;
    case 4: echo "4";        // but we can tell the typechecker we want it
    // FALLTHROUGH
    default: echo "5";
  }
}

fallthrough(4);

Output

45

使用// FALLTHROUGH要告诉我们的是通过故意落在typechecker。

类属性初始化

Hack需要将类属性在使用之前初始化为其适当注释类型的值。

  • 必须使用值初始化所有不可为空的静态类属性。
  • 默认情况下,没有初始值的Nullable 静态类属性具有null值。
  • 必须在构造函数中初始化所有不可为空的非静态类属性。
  • 默认情况下,未在构造函数中初始化的Nullable 非静态类属性将具有null值。
  • 在构造函数中初始化其属性之前,您不能在类上调用公共或私有实例方法。
  • 在构造函数中初始化属性之前,您可以调用私有实例方法,只要属性在访问该属性之前在该私有调用链的某处初始化即可。

方法继承

父类定义一个方法,其子类覆盖它。这很常见 Hack有一些关于重写方法必须遵循的方法的规则。

  • 任何重写方法的参数都必须匹配参数计数和每个参数上的类型。
  • 覆盖方法的返回类型可能具有比其父代更具体的类型; 当然,它们必须是兼容的(例如,arraykey在父母中,string在孩子中)。
以上内容是否对您有帮助:
在线笔记
App下载
App下载

扫描二维码

下载编程狮App

公众号
微信公众号

编程狮公众号