首頁  >  文章  >  後端開發  >  一起來分析為什麼不能在PHP中使用泛型

一起來分析為什麼不能在PHP中使用泛型

WBOY
WBOY轉載
2022-03-29 10:29:575517瀏覽

本篇文章為大家帶來了關於PHP的相關知識,主要介紹了為什麼不能在PHP中使用泛型,下面將深入探討泛型和PHP背後的情況,理解為什麼泛型還不支持身為一等公民,希望對大家有幫助。

一起來分析為什麼不能在PHP中使用泛型

推薦學習:《PHP教程

為什麼我們不能在PHP 中使用泛型

我們將深入探討泛型和PHP 背後的情況。理解為什麼泛型在 PHP 中還不被支持作為一等公民,這非常有趣,而且非常重要。

一起來分析為什麼不能在PHP中使用泛型

讓我們看看。

PHP 中沒有泛型。這就是去年的 Nikita 的結論。這根本不可行。

為了理解 Nikita 為什麼這麼說,我們需要看看如何實現泛型。一般來說,有三種可能的方法;支援泛型的程式語言大多使用這三種方法之一。

第一個稱為 單態泛型。讓我們回到這個系列的第一篇文章,在這篇文章中我展示了這個集合範例:

class StringCollection extends Collection
{
    public function offsetGet(mixed $key): string 
    { /* … */ }
}
class UserCollection extends Collection
{
    public function offsetGet(mixed $key): User 
    { /* … */ }
}

我解釋了我們可以為需要的集合的每種類型,手動建立集合類別的實現。工作量將是巨大的,會有很多程式碼,但是它會起作用。

單態泛型正是這樣做的,但在幕後自動實現。在運行時,PHP 不會知道泛型 Collection 類,而是知道兩個或多個特定實作:

$users = new Collection<User>();
// Collection_User
$slugs = new Collection<string>();
// Collection_string

單態泛型是一種完全有效的方法。例如,Rust 就使用它們。其一個優點是有一系列的效能提升,因為在運行時沒有更多的泛型類型檢查,所以在運行程式碼之前,這些檢查都是分開的。

但這立刻讓我們想到了 PHP 中單態泛型的問題。 PHP 不會像Rust 那樣將一個泛型類別分成幾個具體實現的顯式編譯步驟;最重要的是:單態泛型確實需要相當多的內存,因為你在製作同一個類別的多個副本,但有一些差異。對於已編譯的Rust 二進位檔案來說,這可能不是一個大問題,但對於從中心點(伺服器)運行的PHP 程式碼來說,這是一個嚴重的問題;可能每秒處理數百或數千個請求。

下一個選項是具體化泛型。這是一個實現,其中泛型類別保持原樣,類型資訊在運行時動態評估類型資訊。 C# 和 Kotlin 實作了泛型,它是最接近 PHP 當前類型系統的,因為 PHP 在執行時執行所有類型檢查。這裡的問題是需要大量的核心程式碼重構才能使具體化泛型發揮作用,你可以想像,隨著我們在運行時進行越來越多的類型檢查,一些效能開銷會逐漸增加。

這將我們帶到最後一個選項:在運行時完全忽略泛型。就像它們不在那裡一樣;畢竟,例如集合類別的泛型實現無論如何都可以處理所有類型的輸入。

因此,如果我們在運行時忽略所有泛型類型檢查,則不會有任何問題。

好吧,沒有那麼快。在執行時間忽略泛型類型 —— 順便說一下,它被稱為類型擦除,Java 和 Python 會這樣做 —— 這給 PHP 帶來了一些問題。

舉一個例子:PHP 不僅使用類型進行驗證,它還使用類型資訊將值從一種類型動態轉換為另一種類型—— 這就是我在本系列的第一篇文章中提到的類型雜耍:

function add(int $a, int $b): int 
{
    return $a + $b;
}
add(&#39;1&#39;, &#39;2&#39;) // 3;

如果PHP 忽略了這個「字串」集合的泛型類型,並且我們不小心向它添加了一個整數,那麼如果泛型類型被刪除,它將無法警告我們:

$slugs = new Collection<string>();
$slugs[] = 1; // 1 不会被转换为 &#39;1&#39;

類型擦除的第二個也是更重要的問題—— 也許你現在已經在螢幕上大喊大叫了—— 是類型消失了。如果泛型類型在運行時被刪除,我們為什麼要添加它們?

這在 Java 和 Pyton 中是有意義的,因為在使用靜態分析器執行程式碼之前會檢查所有類型定義。例如,Java 在編譯程式碼時會執行一個內建的靜態分析器; PHP 根本不會做的事情:沒有編譯步驟,當然也沒有內建的靜態類型檢查器。

另一方面… 類型檢查的所有優點,我們在之前的文章中討論過的那些;它們不是來自 PHP 的內建執行時間類型檢查器。當 PHP 的類型檢查器告訴我們有問題時,我們已經在執行程式碼了。一個類型錯誤本質上是讓我們的程式崩潰。

相反,類型檢查的大部分附加價值來自不需要我們執行程式碼的靜態分析器。只要程式設計師提供足夠的類型信息,他們就能很好地確保不會出現運行時類型錯誤。這並不意味著你的程式碼中不能有任何錯誤,但可以編寫完全靜態檢查並且在運行時不會產生任何類型錯誤的 PHP 程式碼。最重要的是:我們在編寫程式碼時獲得了所有靜態洞察;這是任何類型系統中最有價值的部分,與執行時間類型檢查無關。

那麼我們真的需要運行時類型檢查嗎?因為這是目前無法在 PHP 中新增泛型的主要原因:對於 PHP 來說,在執行時間驗證泛型類型太複雜或太耗費資源。

原文網址:https://stitcher.io/blog/generics-in-php-3

翻譯網址:https://learnku.com/php/t/ 66486

推薦學習:《PHP影片教學

以上是一起來分析為什麼不能在PHP中使用泛型的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:learnku.com。如有侵權,請聯絡admin@php.cn刪除