php小編柚子探討了一個常見問題:有沒有辦法約束(通用)類型參數?在PHP中,我們經常需要對函數或方法的參數進行類型約束,以確保傳入的參數符合特定的類型要求。然而,對於通用類型參數,如數組或對象,目前還沒有直接的約束方式。但是,我們可以透過編寫更嚴格的類型檢查邏輯來實現對通用類型參數的約束,以確保參數的正確性和一致性。在本文中,我們將探討幾種實現通用類型參數限制的方法,以及它們的優缺點。
我剛開始學習泛型。因此,我嘗試為在某些 protobuf 訊息上運行的自訂資料庫通用一個驅動程式。
我想找到一種方法來進一步約束我的泛型類型,但作為指針,即確保(告訴編譯器)約束 e 實現了另一種方法。
首先,我限制了資料庫可以處理的實體。
type entity interface { pb.msga | pb.msgb | pb.msgc }
然後,編寫了一個描述資料庫功能的通用接口,以便處理各自的原始訊息的不同服務可以使用它:
type db[e entity] interface { get(...) (e, error) list(...) ([]e, error) ... }
到目前為止一切順利。但是,我還希望在與資料庫通訊時對這些實體進行(反)序列化,以便透過網路發送、克隆和合併。像這樣的事情:
func encode[e entity](v *e) ([]byte, error) { return proto.marshal(v) }
但是,上面的程式碼給了以下錯誤:
cannot use val (variable of type *e) as type protoreflect.protomessage in argument to proto.marshal: *e does not implement protoreflect.protomessage (type *e is pointer to type parameter, not type parameter)
問題是proto.marshal
需要實體(*e)來實現proto.message
接口,即protoreflect()
方法,我所有的實體類型都實作了該方法,但它不受約束,編譯器無法推斷。
我還嘗試將實體定義為:
type Entity interface { *pb.MsgA | *pb.MsgB | *pb.MsgC proto.Message }
但是,除了我需要執行一些額外的 protreflect 操作來實例化實體指標所引用的 proto.messages 之外,這感覺不太對。
你可以這樣做:
func encode[m interface { *e; proto.message }, e entity](v m) ([]byte, error) { return proto.marshal(v) }
如果您想要比上面更簡潔的語法,您可以取消訊息約束:
type Message[E Entity] interface { *E proto.Message } func Encode[M Message[E], E Entity](v M) ([]byte, error) { return proto.Marshal(v) }
https://www.php.cn/link/20ba66f905957b34253d9d7abde919f3
以上是有沒有辦法約束(通用)類型參數?的詳細內容。更多資訊請關注PHP中文網其他相關文章!