W3Cschool
恭喜您成為首批注冊(cè)用戶
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
Refining類型基本上確定一種類型的值也是另一種類型。
假設(shè)您想要使用給定類型并將該特定類型細(xì)化為另一種兼容類型。Hack允許通過(guò)在控制流情況下使用三個(gè)構(gòu)造:
請(qǐng)記住,可空類型允許變量的值為其類型或null。有時(shí)您只想使用null該類型的非部分內(nèi)容。您可以使用空檢查來(lái)細(xì)化可空類型。
<?hh
namespace Hack\UserDocumentation\Types\Refining\Examples\Nullable;
function foo(?int $x): int {
$a = 4;
if ($x !== null) { // refine $x to just an int by verifying it is not null
return $x + $a; // guaranteed that $x is not null now
}
return $a;
}
var_dump(foo(5));
Output
int(9)
請(qǐng)記住,它mixed代表任何可注釋類型(可空類型除外)。mixed可以通過(guò)使用內(nèi)置類型的查詢功能來(lái)將其細(xì)化為更具體的原始類型is_int(), is_float(), is_string()等等
<?hh
namespace Hack\UserDocumentation\Types\Refining\Examples\Mixed;
function foo(mixed $x): int {
$a = 4;
if (is_int($x)) { // refine $x to int by checking to see if $x is an int
return $x + $a;
} else if (is_bool($x)) {
return (int) $x + $a; // know it is a bool, so can do safe cast
}
return $a;
}
var_dump(foo(true));
Output
int(5)
有時(shí)你想知道一個(gè)對(duì)象是一個(gè)父類的子對(duì)象還是實(shí)現(xiàn)一個(gè)特定的接口。您可以使用instanceof支票來(lái)幫助做出這一決定。
<?hh
namespace Hack\UserDocumentation\Types\Refining\Examples\Obj;
interface I {
public function foo(): string;
}
class Base implements I {
public function foo(): string {
return "Base";
}
}
class Child extends Base {
// The __Override attribute is discussed in the section on attributes
// TODO: LINK HERE WHEN READY!
<<__Override>>
public function foo(): string {
return "Child";
}
}
function bar(Base $b): Child {
if ($b instanceof Child) { // refine $b to Child, a subclass of Base
echo $b->foo(); // "Child"
return $b;
}
echo $b->foo(); // "Base"
return new Child();
}
function baz(I $i): Child {
// guarantee that the interface will be a Child
invariant($i instanceof Child, "Not Child");
echo $i->foo(); // "Child"
return $i;
}
function refine_object(): void {
$c = new Child();
bar($c);
bar(new Base());
baz($c);
}
refine_object();
Output
ChildBaseChild
看看這個(gè)例子。
<?hh
namespace Hack\UserDocumentation\Types\Refining\Examples\Unresolved;
interface I {
public function i_method(): bool;
}
abstract class Base {
abstract public function foo(): string;
}
class Child1 extends Base implements I {
<<__Override>>
public function foo(): string {
return "Child1";
}
public function i_method(): bool {
return true;
}
}
class Child2 extends Base {
<<__Override>>
public function foo(): string {
return "Child2";
}
}
function bar(Base $b): void {
if ($b instanceof I) { // refine $b to interface I, but makes $b unresolved
echo $b->i_method();
}
// This is a type error!
// Given the instanceof check above, we have now made $b unresolved, a union
// between a type of I and Base. So we can only call methods common to both.
// which in this case there are none.
echo $b->foo();
}
function unresolved(): void {
$c = new Child1();
bar($c);
}
unresolved();
Output
1Child1
即使bar()
是在通過(guò)了Base
,和所有兒童Base
實(shí)行foo()
,一旦instanceof
支票上完成$b
,并檢查返回true
時(shí),typechecker必須假設(shè)$b
現(xiàn)在是一個(gè)未解決的類型兩者的Base
和I
。而且由于不是所有的執(zhí)行者I
都必須處于層次結(jié)構(gòu)中Base
,我們不能保證foo()
不再有可用性。
還有一個(gè)特殊功能:
invariant(<bool expression of fact>, "Message if not")
可以在外部控制流情況下使用。它本質(zhì)上是對(duì)類型檢查器的一個(gè)斷言,即你在布爾語(yǔ)句中聲明的是事實(shí)和真實(shí)的。
在上述任何精煉方案中,可以使用invariant()與條件檢查相反的方法。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號(hào)-3|閩公網(wǎng)安備35020302033924號(hào)
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號(hào)
聯(lián)系方式:
更多建議: