W3Cschool
恭喜您成為首批注冊用戶
獲得88經(jīng)驗值獎勵
與亞型相關的一個看似與直覺相反的領域是泛型。
<?hh
namespace Hack\UserDocumentation\Generics\Subtypes\Examples\Intuitive;
function echo_add(num $x, num $y): void {
echo $x + $y;
}
function get_int(): int {
return rand();
}
function run(): void {
$num1 = get_int();
$num2 = get_int();
echo_add($num1, $num2); // int is a subtype of num
}
run();
Output
2229204202
由于int是一個子類型num,類型轉換器通過傳遞int一個函數(shù)是完全正確的num。如果你傳遞一個float函數(shù)就沒問題了。如果你傳遞一個int和一個float函數(shù),也沒關系。
但是,你認為類型分析者應該接受嗎?
<?hh
namespace Hack\UserDocumentation\Generics\Subtypes\Examples\CounterIntuitive;
class Box<T> {
private Vector $box;
public function __construct(int $firstItem) {
$this->box = Vector {$firstItem};
}
public function add(T $v) {
$this->box[] = $v;
}
}
function addRandomToBox(Box<num> $x): void {
$x->add(rand());
}
function createBox(): Box<int> {
return new Box(3);
}
function run(): void {
$box = createBox(); // we have a Box<int>
addRandomToBox($box); // typechecker cannot guarantee a Box<int> now.
var_dump($box); // HHVM doesn't care since we erase generics anyway.
}
run();
Output
object(Hack\UserDocumentation\Generics\Subtypes\Examples\CounterIntuitive\Box)#2 (1) {
["box":"Hack\UserDocumentation\Generics\Subtypes\Examples\CounterIntuitive\Box":private]=>
object(HH\Vector)#1 (2) {
[0]=>
int(3)
[1]=>
int(123434323)
}
}
這似乎是應該是有效的傳遞Box<int>一個函數(shù)期望一個Box<num>自從int是一個子類型num。然而,在泛型的情況下,子類型關系與其原始類型的對應關系并不一致。
原因是因為你的泛型對象是通過引用傳遞的,所以類型檢查者沒有辦法安全地知道你是否正在修改Boxin addRandomToBox()以包含不是的東西num。雖然明顯地向我們說,我們正在添加int中addRandomToBox(),該typechecker實際上不考慮發(fā)生了什么。所以不確定的是,返回給我們的還是一個Box<int>。
HHVM運行時并不在意,因為我們在運行時會刪除泛型。
由于不可變的集合不能被改變array(即拷貝而不是引用),泛型與上面討論的子類型關系實際上會通過類型檢查器。這是因為類型檢查器可以保證實體在返回給調(diào)用者時不會被改變。
<?hh
namespace Hack\UserDocumentation\Generics\Subtypes\Examples\Immutable;
function addRandomToArray(array<num> $x): void {
$x[] = 3.2; // this is a copy, not a reference
}
function createArray(): array<int> {
return array(3);
}
function run(): void {
$arr = createArray(); // we have a array<int>
// typechecker CAN guarantee array<int> now since what is received by
// addRandomToArray() is a copy (passed-by-value)
addRandomToArray($arr);
var_dump($arr); // Still only going to contain 3, not the 3.2.
}
run();
Output
array(1) {
[0]=>
int(3)
}
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網(wǎng)安備35020302033924號
違法和不良信息舉報電話:173-0602-2364|舉報郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: