协议缓冲区中的继承

Viv*_*nha 25 java protocol-buffers protocol-buffers-3

如何处理Google Protocol Buffers 3.0中的继承?

Java等效代码:

public class Bar {
    String name;
}
public class Foo extends Bar {
    String id;
}
Run Code Online (Sandbox Code Playgroud)

什么是Proto等效代码?

message Bar {
    string name = 1;
}
message Foo {
    string id = 2;
}
Run Code Online (Sandbox Code Playgroud)

Ken*_*rda 31

协议缓冲区不支持继承.相反,考虑使用组合:

message Foo {
  Bar bar = 1;
  string id = 2;
}
Run Code Online (Sandbox Code Playgroud)

但是,这就是说,你可以使用一种技巧,就像继承一样 - 但这是一个丑陋的黑客,所以你应该小心使用它.如果您定义了以下消息类型:

message Bar {
  string name = 1;
}
message Foo {
  string name = 1;
  string id = 2;
}
Run Code Online (Sandbox Code Playgroud)

这两种类型是兼容的,因为Foo包含了字段的超集Bar.这意味着如果您有一种类型的编码消息,则可以将其解码为另一种类型.如果您尝试解码Baras类型Foo,id则不会设置该字段(并将获得其默认值).如果解码Foo为类型Bar,则该字段id将被忽略.(请注意,这些规则与在一段时间内向类型添加新字段时适用的规则相同.)

您可以使用它来实现类似继承的东西,通过使用几个类型,所有类型都包含"超类"字段的副本.但是,这种方法存在一些大问题:

  • 要将类型的消息对象转换Foo为类型Bar,您必须序列化并重新解析; 你不能只是演员.这可能是低效的.
  • 将新字段添加到超类非常困难,因为您必须确保将字段添加到每个子类,并且必须确保这不会产生任何字段数冲突.


And*_*ner 16

请参阅Protocol Buffer Basics教程:

不要去寻找类继承类似的工具,但协议缓冲区不会这样做.

  • 鉴于 Protocol Buffers 绑定的大多数语言都是面向对象的并且支持继承,Protobufs 放弃对继承的支持似乎有点疏忽。这将像 EJB(仅为面向对象的 Java 语言构建)一样愚蠢到忽略继承的支持...... (6认同)
  • 无需添加继承,它仅用于将数据集从一侧带到另一侧。如果一方或另一方想要进行构建继承构造的计算,则数据通信不会产生任何后果。 (3认同)
  • 我认为没有这样做的主要原因是因为它增加了 id 冲突的风险,特别是如果存在版本不匹配并且一侧使用较旧的模式。这种情况的发生不太明显,因为“基类”的 id 可能在其他地方,甚至可能不在与派生类相同的文件中。 (3认同)
  • @Volksman“大多数语言”,所以_并非所有_都支持继承。例如,Google 的主要生产语言之一 Go 就没有。由于协议缓冲区是 Google 内的标准交换格式,因此它们被设计为使用生产语言中可用的功能。 (3认同)
  • 知道他们为什么不这样做?我的意思是,即使将来,它听起来也不像是他们想要添加的东西 (2认同)
  • 我*认为*这会导致效率低下。porto-buffer 的核心功能之一是高效打包。分配给变量的整数的较低值可确保优化打包,其次它们必须是唯一的。现在,当创建多级继承时,将很难跟踪分配给基本结构中的属性的整数。 (2认同)