天天看點

《Hack與HHVM權威指南》——2.5 重溫未決的類型

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

在引導範例中,我們看到了當你使用類型檢查器的時候,它們能夠推斷泛型類的類型實參。這裡,類型檢查器知曉,對于類型形參tval,wrapper已經用int類型替代進行執行個體化了。

<code>$w = new wrapper(20);</code>

這個推斷算法的準确細節已經超出了這裡的讨論範圍,但是這裡仍然有一些需要知曉的結論。

類型檢查器應該接受下面的代碼嗎?

直覺上來說,它應該是被接受的,事實也是這樣。類型檢查器知道在main()函數的最後一行,變量$wrapper是一個整型的wrapper,是以允許這個調用。

那麼,換成下面的代碼呢?

看起來這應該不允許執行,事實也确實如此。

那麼,如果我們再換成如下的代碼呢?

正如我們在第一個例子中看到的一樣,類型檢查器似乎明白$wrapper在第一行後面是個wrapper。是以看起來類型檢查器應該報告一個錯誤:在wrapper上,你不應該對setvalue()傳遞一個字元串作為實參。但是事實上,這段代碼是合法的。

這就是類型檢查器使用未決的類型的另外一個地方。我們首次接觸到它們在1.6.2節,在那裡,它們被 “類型檢查器用來跟蹤一個變量”,這個變量能夠在一個程式中的單一點擁有不同的類型,而這決定于達到這個“點”代碼的邏輯路徑。而對于泛型,類型檢查器使用未決的類型來記住那些還沒有被明确規定的類型,當類型檢查器看到更多的代碼後,這裡将随時保持對它們進行調整的自由。

在第一行的後面,類型檢查器已經非常肯定變量$w是個wrapper,但是關于它的類型實參是什麼,這裡還沒有明确的指引。它想起以前曾經看到這個對象被當作類型wrapper進行使用,但是int的類型實參是個未決的類型。于是,它繼續向上檢視相關調用$w-&gt;setvalue('a string'),類型檢查器檢視變量$w的類型,來看這個調用是否合法。當它看到未決的類型實參時,它将把字元串添加到未決的類型中去,而不是抛出一個錯誤。到此為止,就類型檢查器來說,變量$w或者是wrapper或者是wrapper。

而對于讀者來說,直覺上并不是這樣的:很明顯在$w内有個字元串。但是類型檢查器不知道wrapper的語義:它并不明白wrapper隻包含單個值。類型檢查器所知曉的就是$w好像被當成wrapper進行使用,還好像是個wrapper。

當檢查到一個未決的類型實參違反某個類型标注的時候,它将變成一個“已決的類型”。這個例子将展示一切相關的内容:

這次,類型檢查器将在最後一行報告一個錯誤。當變量$w被傳遞給函數takes_wrapper_of_int()時,檢查到它違反了函數的形參類型标注。在這點上,變量$w的類型是“已決的”。類型檢查器已經看到變量$w應該是一個wrapper類型的确鑿證據。既然這個類型是“已決的”了,類型檢查器在對setvalue()方法的調用檢查上也就不會寬大處理了。在一個已決的類型wrapper的wrapper執行個體上調用“setvalue('a string')”是非法的,是以類型檢查器報告了一個錯誤。