天天看點

《Hack與HHVM權威指南》——2.6 泛型和亞型

本節書摘來自華章出版社《hack與hhvm權威指南》一書中的第2章,第2.6節,作者 owen yamauchi,更多章節内容可以通路雲栖社群“華章計算機”公衆号檢視。

讓我們回到關于wrapper類的引導範例。類型檢查器應該接受下面的代碼嗎?

那麼問題來了,傳遞一個整型的wrapper到一個期待值為num的wrapper的話,這個操作是非法的嗎?看起來應該是這樣的:int是num的亞型(意味着任何為int的值都會是個num),是以看起來wrapper應該同樣是wrapper的亞型。

事實上,對于這個例子,類型檢查器将會報告一個錯誤。對于類型檢查器來說,我們關于int和num的亞型關系傳遞給wrapper和wrapper之間亞型關系的假設是不成立的。

為了說明其中的緣由,我們請思考下面的代碼,函數takes_wrapper_of_num()能夠做這個事情:

對于它自己來說,這是合法的:設定一個wrapper内部的值為一個float類型的值。但是如果你傳遞一個wrapper到上述版本的函數takes_wrapper_of_num()中,這将會導緻wrapper再也不是整型。是以類型檢查器不接受對函數takes_wrapper_of_num()傳遞wrapper。這并不是類型安全的。需要特别說明的是,這裡有一項鐵的規則:類型檢查器并不思考函數takes_wrapper_of_num()實際上在做什麼。即使函數takes_wrapper_of_num()是空的,類型檢查器仍然會報告一個錯誤。

現在,我們看另外一段代碼,類型檢查器應該接受這段代碼嗎?

雖然這次直覺上看起來一切正常,但是類型檢查器會再一次報告錯誤。原因是非常相似的。設想一下,我們在空白處填上如下内容:

這很明顯是非法的——在main()函數執行後,任何對函數returns_wrapper_of_int()的調用都會傳回某一個非int類型的wrapper。是以,再一次,對于函數returns_wrapper_of_num()裡面的return語句,類型檢查器會報告一個錯誤。

數組和集合

數組和hack的不可變集合類(immvector、immmap、immset和pair)表現上是不一緻的。舉例來說,它們遵從着很直覺的概念,array是array的亞型。下例中對數組的使用是合法的:

類似的行為對于不可變集合類的值類型注3也是有效的。不必考慮你是使用它們自己的名字進行注解,還是用類似constvector這樣的接口名字(這是推薦的)進行注解:

為什麼這對于數組和不可變集合是合法的,而對于wrapper卻是非法的?

就不可變集合來說,原因很簡單:它們是不可變的。即使你傳遞一個immvector到參數為immvector的函數,這個函數也沒有辦法設定一個非整型值到vector中。這裡沒有任何方法可以破壞vector隻能包含整數的規矩。

就數組而言,道理也是一樣的。出于相同的目的,由于值傳遞語義數組和不可變集合在表象上幾乎一緻。在上一個示例中,從takes_array_of_num()的視角,在函數takes_array_of_int()主體内的數組實際上是隻讀的。函數takes_array_of_num()不能夠導緻數組内部具有非整型值。因為它根本就無法通路原始數組,隻有複制的權限。

繼續閱讀