首頁  >  文章  >  後端開發  >  無法推斷函數建構函數的泛型參數中的類型

無法推斷函數建構函數的泛型參數中的類型

PHPz
PHPz轉載
2024-02-09 08:00:32581瀏覽

無法推斷函數建構函數的泛型參數中的類型

php小編柚子將為大家解答一個常見的問題:在建構子的泛型參數中,無法推論出類型的原因。在PHP中,泛型參數的類型推論是透過參數的預設值來實現的。然而,在建構函式中,由於參數是在物件建立之前就被傳入的,因此無法透過物件的實例來推斷參數的類型。這就導致了建構函式中無法推斷出泛型參數的類型,需要手動指定型別來解決這個問題。

問題內容

我在 go 中有一些通用程式碼,其中有一個具有通用參數的「主」類型和許多應該共享相同通用參數的「從」類型。程式碼看起來與此類似:

type Doer[T any] interface {
    ModifyA(*A[T])
}

type B[T any] struct {
}

func NewB[T any]() *B[T] {
    return new(B[T])
}

func (b *B[T]) ModifyA(a *A[T]) {
    // Do a thing
}

type A[T any] struct{}

func NewA[T any]() A[T] {
    return A[T]{}
}

func (a *A[T]) Run(doers ...Doer[T]) {
    for _, doer := range doers {
        doer.ModifyA(a)
    }
}

func main() {
    a := new(A[int])
    a.Run(NewB())   // error here
}

基本上,使用者應該在 a 上定義 t ,然後 b 上的 t 應該是相同的。此類程式碼可以在支援泛型的其他語言中工作,但在 go 中,我在註解行處收到 cannot infer t 編譯錯誤(請參閱此處的 go playground 程式碼)。在我看來, a 上的類型參數設定為 int ,因此 b 上的類型參數也應設定為 int 。我可以改為呼叫 newb[int]() ,但這對我來說似乎太冗長。為什麼會出現這種情況?

解決方法

這是「為什麼編譯器不能根據傳回類型的使用方式推斷類型參數?」的變體。答:因為從 go 1.20 開始,這不是類型推論的工作方式。

型別推論適用於:

  • 類型參數清單
  • 使用已知類型參數初始化的替換映射 m(如果有)
  • 普通函數參數的(可能為空)列表(僅在函數呼叫的情況下)

如果您一一檢查這些規則:

  • newb() 有型別參數清單嗎?不。您在呼叫它時沒有指定類型參數。

  • 是否有其他已知的型別參數可以用來推論其他型別參數?不,您根本沒有提供任何類型參數。請注意,這種情況適用於您提供部分數量的類型參數的函數調用,例如:

    func foo[T any, U *T]() {}

    在上面您只能提供t,例如float64,編譯器將使用t -> float64 建構替換映射,然後推斷 u -> *float64

  • #最後,有普通函數參數的列表嗎?否。 newb 為空。

僅此而已。編譯器不會根據函數傳回類型的使用方式推斷類型參數。

在撰寫本文時,正在討論的相關提案有:

以上是無法推斷函數建構函數的泛型參數中的類型的詳細內容。更多資訊請關注PHP中文網其他相關文章!

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