Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

what's the right way to do polymorphism with protocol buffers?

I'm trying to long-term serialize a bunch of objects related by a strong class hierarchy in java, and I'd like to use protocol buffers to do it due to their simplicity, performance, and ease of upgrade. However, they don't provide much support for polymorphism. Right now, the way I'm handling it is by having a "one message to rule them all" solution that has a required string uri field that allows me to instantiate the correct type via reflection, then a bunch of optional fields for all the other possible classes I could serialize, only one of which will be used (based on the value of the uri field). Is there a better way to handle polymorphism, or is this as good as I'm going to get?

like image 461
user364003 Avatar asked Jun 10 '10 21:06

user364003


People also ask

Does Protobuf support polymorphism?

Bookmark this question. Show activity on this post. I'm trying to long-term serialize a bunch of objects related by a strong class hierarchy in java, and I'd like to use protocol buffers to do it due to their simplicity, performance, and ease of upgrade. However, they don't provide much support for polymorphism.

What is the point of protocol buffers?

Protocol Buffers (Protobuf) is a free and open-source cross-platform data format used to serialize structured data. It is useful in developing programs to communicate with each other over a network or for storing data.

What is oneof in Protobuf?

Protocol Buffer (Protobuf) provides two simpler options for dealing with values that might be of more than one type. The Any type can represent any known Protobuf message type. And you can use the oneof keyword to specify that only one of a range of fields can be set in any message.


2 Answers

In proto3 the extend keyword has been replaced. From the 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; } 

But beware: Any is essentially a bytes blob. Most of the times it is better to use Oneof:

syntax = "proto3";  message A {     string a = 1; }  message B {     string b = 1; }  message Foo {   oneof bar {     A a = 1;     B b = 2;   } } 
like image 155
RickyA Avatar answered Sep 28 '22 08:09

RickyA


There are a few techniques for implementing polymorphism. I try to cover them all here: Protocol Buffer Polymorphism

My preferred approach uses nested extensions:

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; } 
like image 37
Jon Parise Avatar answered Sep 28 '22 08:09

Jon Parise