Estoy tratando de serializar a largo plazo un conjunto de objetos relacionados por una sólida jerarquía de clases en java, y me gustaría utilizar los búferes de protocolo para hacerlo debido a su simplicidad, rendimiento y facilidad de actualización. Sin embargo, no proporcionan mucho apoyo para el polimorfismo. En este momento, la forma en que lo estoy manejando es teniendo una solución de "un solo mensaje para gobernarlos todos" que tiene un campo requerido de cadena uri que me permite crear una instancia del tipo correcto a través de la reflexión, luego un conjunto de campos opcionales para todo el otras clases posibles que podría serializar, solo una de las cuales se usará (según el valor del campo uri). ¿Hay una mejor manera de manejar el polimorfismo, o esto es tan bueno como lo que obtendré?¿cuál es la forma correcta de hacer polimorfismo con los búferes de protocolo?
Respuesta
¿Ha considerado usar extensions? Puede hacer que su campo uri determine el tipo que se va a usar y luego solo cargue las extensiones apropiadas. Si sabe que sus campos son mutuamente excluyentes, entonces puede reutilizar la identificación de campo entre extensiones separadas.
Tiene que manejarlo todo usted mismo porque los búferes de protocolo no están diseñados para ser autodescriptivos más allá de una simple lista de valores. Esto se aborda en la página de técnicas de google.
Consulte Extensions and Nested Extensions para obtener una forma un poco más clara de hacerlo.
Existen algunas técnicas para implementar el polimorfismo. Trato de cubrir todas aquí: Protocol Buffer Polymorphism
Mi enfoque preferido utiliza anidado extensions: solución
message Animal
{
extensions 100 to max;
enum Type
{
Cat = 1;
Dog = 2;
}
required Type type = 1;
}
message Cat
{
extend Animal
{
required Cat animal = 100; // Unique Animal extension number
}
// These fields can use the full number range.
optional bool declawed = 1;
}
message Dog
{
extend Animal
{
required Dog animal = 101; // Unique Animal extension number
}
// These fields can use the full number range.
optional uint32 bones_buried = 1;
}
Me parece (de los experimentos de Python) que este enfoque todavía permite que un mensaje use ambas extensiones al mismo tiempo. Así que no veo cómo esto difiere del enfoque con los campos de mensaje opcionales y el campo de sugerencia de tipo, a excepción de la sintaxis más compleja. – MvG
Además, ¿por qué necesita tipos aquí? ¿No es suficiente usar 'HasExtension' para verificar qué tipo es el mensaje? – Ixanezis
Sí, solo puede usar HasExtension para averiguar si un mensaje de Animal dado contiene una extensión Cat o Dog. –
de Jon es correcta y trabajando pero bastante raro (para mí). Pero Protocol Buffers es bastante simple, lo que puede hacer algo por el estilo:
enum Type {
FOO = 0;
BAR = 1;
}
message Foo {
required Type type = 1;
}
message Bar {
required Type type = 1;
required string text = 2;
}
Básicamente mensaje de la barra se extiende mensaje de Foo (de lado práctico, por supuesto). La implementación en Java también es simple:
Bar bar = Bar.newBuilder().setType(Type.BAR).setText("example").build();
byte[] data = bar.toByteArray();
----
Foo foo = Foo.parseFrom(data);
if(foo.getType() == Type.BAR){
Bar bar = Bar.parseFrom(data);
System.out.println(bar.getText());
}
Lo sé, no es una solución elegante, pero es simple y lógica.
Esto está bien, si Foo y Bar pertenecen al mismo servicio. El motivo para usar las extensiones de mensaje es permitir que los clientes extiendan mensajes pertenecientes a un servicio. Por lo tanto, un servicio de almacenamiento podría exportar Foo y permitir extensiones, y luego un cliente podría decidir que también desea almacenar datos de Bar dentro de ese Foo. El servicio de almacenamiento publicaría foo.proto como parte de su definición de API, y el cliente extendería eso con bar.proto que importa Foo desde foo.proto. –
Esto no responde a la pregunta original, pero puede ser útil para otros que utilicen v3 de Protocol Buffers. La versión 3 no permite la palabra clave extensions
. Al ejecutar protoc
en el siguiente archivo, se genera un error con el mensaje Extension ranges are not allowed in proto3
.
syntax = "proto3";
message BaseMessage {
extensions 100 to max;
}
Una solución un poco mejor, para mí, que la respuesta de @ Łukasz Marciniak.
Si Bar extiende Foo, simplemente escriba:
message Bar {
optional Foo foo = 1;
optional double aDouble = 2;
}
message Foo {
optional string aString = 1;
}
Así que si evoluciona Foo Foo único mensaje es modificado.
En proto3 la palabra clave extend
ha sido reemplazada. Desde el docs: If you are already familiar with proto2 syntax, the Any type replaces extensions.
syntax = "proto3";
import "google/protobuf/any.proto";
message Foo {
google.protobuf.Any bar = 1;
}
Pero cuidado: Any
es esencialmente una mancha bytes.La mayoría de las veces es mejor usar Oneof
:
syntax = "proto3";
message A {
string a = 1;
}
message B {
string b = 1;
}
message Foo {
oneof bar {
A a = 1;
B b = 2;
}
}
- 1. Protocolo de búferes con JPA
- 2. ¿Cómo usar los búferes de protocolo?
- 3. ¿Cuál es la mejor manera de usar decimales y fechas con búferes de protocolo?
- 4. Alternativas a los búferes de protocolo
- 5. Diccionario en búferes de protocolo
- 6. ¿Cuál es la forma correcta de redirigir?
- 7. búferes de protocolo con c & C++
- 8. ¿Cuál es la forma correcta de usar maxAge con Express.js?
- 9. ¿Cuál es la forma correcta de hacer actualizaciones de diseño con páginas CMS?
- 10. ¿Cuál es la forma correcta de mostrar la InnerException completa?
- 11. ¿Cuál es la forma correcta de ocultar una etiqueta HTML?
- 12. Extensión de búferes de protocolo en Java
- 13. ¿Cuál es la forma correcta de sangrar Erlang?
- 14. ¿Cuál es la forma correcta de usar bitfields en C?
- 15. ¿Cuál es la forma correcta de desconectar un MediaController?
- 16. ¿Cuál es la forma correcta de '#include file' en MVC?
- 17. VC++ 10 MFC: ¿Cuál es la forma correcta de hacer la localización?
- 18. Cuál es la forma correcta de cerrar una conexión TCP
- 19. Integrar búferes de protocolo en Maven2 compilación
- 20. ¿Cuál es la forma correcta de ajustar [NSString stringWithFormat:]?
- 21. ¿Cuál es la forma correcta de detectar Opera usando jQuery?
- 22. ¿Cuál es la forma correcta de rastrear índices en python?
- 23. ¿Cuál es la forma correcta de representar elementos XML nulos?
- 24. Uso de búferes de protocolo con Objective-C
- 25. cuál es la forma correcta de separar datos en couchbase
- 26. ¿Cuál es la forma correcta de pasar una excepción? (C#)
- 27. ¿Cuál es la forma correcta de usar TypeForwardedToAttribute?
- 28. ¿Cuál es la forma correcta de usar @synchronized?
- 29. ¿Cuál es la forma correcta de cargar un ListBox?
- 30. ¿Cuál es la forma correcta de declarar un Doctype HTML5?
Cuidado: en ** proto3 ** las extensiones se han eliminado. – RickyA