Heim  >  Artikel  >  Backend-Entwicklung  >  Gibt es eine Möglichkeit, (generische) Typparameter einzuschränken?

Gibt es eine Möglichkeit, (generische) Typparameter einzuschränken?

王林
王林nach vorne
2024-02-09 13:18:19427Durchsuche

Gibt es eine Möglichkeit, (generische) Typparameter einzuschränken?

PHP-Editor Youzi hat eine häufig gestellte Frage besprochen: Gibt es eine Möglichkeit, (universelle) Typparameter einzuschränken? In PHP müssen wir den Parametern von Funktionen oder Methoden häufig Typbeschränkungen auferlegen, um sicherzustellen, dass die übergebenen Parameter bestimmte Typanforderungen erfüllen. Derzeit gibt es jedoch keine direkte Möglichkeit, generische Typparameter wie Arrays oder Objekte einzuschränken. Wir können jedoch Einschränkungen für allgemeine Typparameter implementieren, indem wir eine strengere Typprüfungslogik schreiben, um die Richtigkeit und Konsistenz der Parameter sicherzustellen. In diesem Artikel untersuchen wir verschiedene Möglichkeiten zur Implementierung generischer Typparametereinschränkungen sowie deren Vor- und Nachteile.

Frageninhalt

Ich habe gerade angefangen, Generika zu lernen. Ich versuche also, einen Treiber für eine benutzerdefinierte Datenbank zu verallgemeinern, die auf einigen Protobuf-Nachrichten ausgeführt wird.

Ich würde gerne einen Weg finden, meinen generischen Typ weiter einzuschränken, aber als Zeiger, d. h. sicherstellen (dem Compiler mitteilen), dass die Einschränkung e eine andere Methode implementiert.

Zuerst habe ich die Entitäten eingeschränkt, die die Datenbank verarbeiten kann.

type entity interface {
   pb.msga | pb.msgb | pb.msgc
}

Dann wurde eine gemeinsame Schnittstelle geschrieben, die die Funktionalität der Datenbank beschreibt, damit sie von verschiedenen Diensten verwendet werden kann, die ihre eigenen Rohnachrichten verarbeiten:

type db[e entity] interface {
   get(...) (e, error)
   list(...) ([]e, error)
   ...
}

So weit so gut. Allerdings möchte ich diese Entitäten bei der Kommunikation mit der Datenbank auch (de)serialisieren, damit sie über das Netzwerk gesendet, geklont und zusammengeführt werden können. Dinge wie diese:

func encode[e entity](v *e) ([]byte, error) {
   return proto.marshal(v)
}

Der obige Code gibt jedoch den folgenden Fehler aus:

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)

Das Problem ist die proto.marshal 需要实体(*e)来实现 proto.message 接口,即 protoreflect()-Methode, die alle meine Entitätstypen implementieren, aber sie ist nicht eingeschränkt und kann vom Compiler nicht abgeleitet werden.

Ich habe auch versucht, die Entität wie folgt zu definieren:

type Entity interface {
   *pb.MsgA | *pb.MsgB | *pb.MsgC
   proto.Message
}

Aber das fühlt sich nicht richtig an, abgesehen von der Tatsache, dass ich einige zusätzliche Schutzoperationen durchführen muss, um die proto.messages zu instanziieren, auf die der Entitätszeiger verweist.

Lösung

Sie können dies tun:

func encode[m interface { *e; proto.message }, e entity](v m) ([]byte, error) {
    return proto.marshal(v)
}

Wenn Sie eine prägnantere Syntax als oben wünschen, können Sie die Nachrichtenbeschränkung aufheben:

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

Das obige ist der detaillierte Inhalt vonGibt es eine Möglichkeit, (generische) Typparameter einzuschränken?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:stackoverflow.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen