【问题标题】:Inheritance in protocol buffers协议缓冲区中的继承
【发布时间】:2017-05-05 17:16:05
【问题描述】:

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

Java 等效代码:

public class Bar {
    String name;
}
public class Foo extends Bar {
    String id;
}

什么是 Proto 等效代码?

message Bar {
    string name = 1;
}
message Foo {
    string id = 2;
}

【问题讨论】:

标签: java protocol-buffers protocol-buffers-3


【解决方案1】:

Protocol Buffers 不支持继承。相反,请考虑使用组合:

message Foo {
  Bar bar = 1;
  string id = 2;
}

不过,话虽如此,您可以使用一个技巧,它类似于继承 - 但这是一种丑陋的 hack,因此您应该谨慎使用它。如果您将消息类型定义为:

message Bar {
  string name = 1;
}
message Foo {
  string name = 1;
  string id = 2;
}

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

您可以使用它来实现类似继承之类的东西,方法是让几种类型都包含“超类”字段的副本。但是,这种方法存在几个大问题:

  • 要将Foo类型的消息对象转换为Bar类型,你必须序列化和重新解析;你不能只投。这可能效率低下。
  • 向超类添加新字段非常困难,因为您必须确保将字段添加到每个子类,并且必须确保这不会造成任何字段编号冲突。

【讨论】:

  • 知道如何从 Java API 调用解码器/编码器吗?
  • 在使用合成时使用 Bar 来解码 Foo 对我来说真的不起作用。
  • @glato 是的,这不适用于合成。它仅在一种类型包含另一种类型的字段的子集时才有效,如我的第二个示例所示。
  • 如果FooBar 共享一个公共字段,这将如何工作?
  • @pooya13 Foo 的字段将hide Bar 的同名字段。
【解决方案2】:

参见Protocol Buffer Basics 教程:

不过,不要去寻找类似于类继承的工具 - 协议缓冲区不会这样做。

【讨论】:

  • 知道他们为什么不这样做吗?我的意思是,这听起来不像是他们想要添加的东西,即使是在未来
  • 认为这会导致效率低下。 porto-buffers 的核心功能之一是有效地打包东西。分配给变量的整数的较低值可确保优化打包,其次它们必须是唯一的。现在,当创建多级继承时,将很难跟踪分配给基础结构中属性的整数..
  • 不需要添加继承,它只是将数据集从一侧带到另一侧。如果一方或另一方想要进行构建继承构造的计算,则数据通信不会产生任何后果。
  • 鉴于 Protocol Buffers 绑定的大多数语言都是 OO 并支持继承,Protobufs 忽略对继承的支持似乎有点疏忽。这将与 EJB(仅为 OO Java 语言构建)一样愚蠢到不支持继承......
  • 我认为它没有完成的主要原因是因为它增加了 id 冲突的风险,特别是如果存在版本不匹配并且一方使用的是旧模式。而且这种情况的发生不太明显,因为“基类”的 id 会在其他地方,甚至可能与派生类不在同一个文件中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-09-18
  • 2021-12-19
  • 2011-11-15
  • 1970-01-01
  • 1970-01-01
  • 2020-04-06
  • 2016-12-19
相关资源
最近更新 更多