sencillos programacion polimorfismo orientada objetos mapa herencia ejemplos clase caracteristicas abstracta abstraccion protocol-buffers

protocol buffers - programacion - ¿Cuál es la forma correcta de hacer polimorfismo con los búferes de protocolo?



polimorfismo java caracteristicas (7)

Estoy tratando de serializar a largo plazo una gran cantidad 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é?


¿Has 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.

Debe manejarlo todo usted mismo, ya que los búferes de protocolo no están diseñados para autodescribirse más allá de una simple lista de valores. Esto se aborda en la página de técnicas de google.


Consulte extensions para obtener una forma ligeramente más clara de hacerlo.


En proto3, la palabra clave extend ha sido reemplazada. De los 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 un blob de 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; } }


Esto no responde a la pregunta original, pero puede ser útil para otros que usan v3 de Protocol Buffers . La versión 3 no permite la palabra clave de extensions . La ejecución de un protoc en el siguiente archivo genera un error con el mensaje Extension ranges are not allowed in proto3 .

syntax = "proto3"; message BaseMessage { extensions 100 to max; }


Hay algunas técnicas para implementar el polimorfismo. Intento abarcarlos todos aquí: Polimorfismo del búfer de protocolo

Mi enfoque preferido usa extensions anidadas:

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; }


La solución de Jon es correcta y funciona, pero bastante extraña (para mí). Pero Protocol Buffers es bastante simple, entonces puedes hacer algo como eso:

enum Type { FOO = 0; BAR = 1; } message Foo { required Type type = 1; } message Bar { required Type type = 1; required string text = 2; }

Básicamente, la barra de mensajes extiende el mensaje Foo (desde el 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.


Una solución un poco mejor, para mí, que la respuesta de @ Łukasz Marciniak.

Si Bar extiende Foo, simplemente escribe:

message Bar { optional Foo foo = 1; optional double aDouble = 2; } message Foo { optional string aString = 1; }

Entonces, si Foo evoluciona solo el mensaje de Foo se modifica.