閱讀541 返回首頁    go windows


《Hack與HHVM權威指南》——第2章 泛型2.1 入門實例

本節書摘來自華章出版社《Hack與HHVM權威指南》一書中的第2章,第2.1節,作者 Owen Yamauchi,更多章節內容可以訪問雲棲社區“華章計算機”公眾號查看。

第2章

泛型
泛型在Hack的類型係統裏麵是個非常強大的特性,泛型可以允許你在不知道流程中傳入的具體類型的情況下,寫出類型安全的代碼。一個類或者函數都可以是泛型的,這意味著它可以讓調用者來選擇傳入的參數類型。
泛型結構體最好的例子就是數組和集合類(關於集合類的更多內容請參見第5章)。不具備明確指出數組內容具體類型的能力,它不可能推斷出索引自數組的任何值的類型,並且設置數組中的一個值不能被類型檢查。這些操作在PHP和Hack中都是非常常見的,並且泛型讓類型檢查器能夠理解並對它們進行核實。
在本章的內容中,我們將對泛型提供的所有特性進行查看和學習。
2.1 入門實例
我們將會從一個非常簡單的例子入手學習:一個包含隨意值的類。你可能在日常練習中從來沒有這麼寫過這樣的代碼注1,但是這是一個對泛型進行介紹的最好例子。在本章的學習中,我們講會使用它作為運行的實例。
為了使一個類“泛型化”,我們可以在類名後麵放置一個由尖括號括起來的、逗號分隔的類型形參列表。一個類型形參可以簡單理解為:一個用大寫T開頭的標識符。在泛型類定義內部,可以在變量標準中使用這些類型形參。主要在如下三個常見的位置(屬性、方法形參、方法的返回標注類型)。
下麵是泛型類的例子:

class Wrapper<Tval> {
  private Tval $value;
  public function __construct(Tval $value) {
    $this->value = $value;
  }
  public function setValue(Tval $value): void {
    $this->value = $value;
  }
  public function getValue(): Tval {
    return $this->value;
  }
}
// There can be multiple type parameters
class DualWrapper<Tone, Ttwo> {
  // ...
}

為了使用這種泛型類,你僅需要像往常一樣對它進行實例化,然後使用得到的結果對象即可。

$wrapper = new Wrapper(20);
$x = $wrapper->getValue();

在這個例子中,得益於Wrapper是泛型的,所以類型檢查器知道$x是個整數。它能夠看到你傳遞了整數到Wrapper的構造函數中,並且推斷出它應該對這個特殊的Wrapper實例的使用進行類型檢查,就好像把類定義中所有的Tval用int進行替代一樣。
在這種情況下,類型檢查過程和你用下麵的這個類對Wrapper類進行替代得到的效果一樣好。

class WrapperOfInt {
  private int $value;
  public function __construct(int $value) {
    $this->value = $value;
  }
  public function setValue(int $value): void {
    $this->value = $value;
  }
  public function getValue(): int {
    return $this->value;
  }
}

然而,對於泛型版本,你可以對這個類使用任何類型,這具有明顯的益處。如果你傳遞一個字符串類型到Wrapper類的構造函數中,那麼這個實例的getValue()方法的返回類型也會是個字符串。你如果你傳遞一個?float類型的值到Wrapper的構造函數中,那麼該實例的getValue()方法的返回類型也將是?float。諸如此類,你可以對能想得到的其他類型進行類似推理判斷。
這就是泛型的真實力量:你可以對Wrapper類寫一個包含任何類型值的單獨實現,但是它仍然是徹底類型安全的。
作為本次說明的最後部分,這裏將介紹如何為一個泛型類的實例寫一個類型標注。語法是一個類名,隨後跟隨著被尖括號括起來的、逗號分隔的類型標注列表。在列表中的每個標注都被稱作類型實參:

function wrapped_input(): Wrapper<string> {
  $input = readline("Enter text: ");
  return new Wrapper($input);
}

類型形參(type parameter)和類型實參(type argument)的關係就和函數形參(function parameter)和函數實參(function argument)的關係一樣。類型實參是泛型類定義中的類型形參在具體使用時的替代品。在本例中,函數返回值是Wrapper類的一個實例,它將告訴類型檢查器應該對這個對象的使用進行類型檢查,就好像對該類定義中的所有Tval替換為string。
2.2 其他泛型實體
類並不是唯一可以被泛型化的實體。

最後更新:2017-05-26 10:01:52

  上一篇:go  2017新年獻詞 | 先跑起來, 再跑得更遠
  下一篇:go  數據脫口秀 | 矽穀軟件大佬跨界黑曆史 那些年做不下去的硬件