当前位置: 首页 > 知识库问答 >
问题:

如何使用原始缓冲区有效地完成继承

华烈
2023-03-14

我有一条基类消息

message Animal {
     optional string name = 1;
     optional int32 age = 2;  
}

以及扩展动物的子类

message Dog{
     optional string breed = 1;
}

因此,在构建狗消息时,我应该能够设置动物的所有字段。我知道这样做的方法(在狗消息中再次声明所有动物字段),但是否可以简单有效地使用原型缓冲区?我还了解了扩展,我明白它只是用于向已经存在的消息添加一个新字段,因此不应该被误解为实现继承的可能解决方案。

使用protobuffers的扩展是否可以实现上述简单的设计?

共有1个答案

郎吉星
2023-03-14

有几种不同的方法可以在协议缓冲区中实现“继承”。您想要哪一个取决于您的用例。

message Animal {
  optional string name = 1;
  optional int32 age = 2;  
}

message Dog {
  required Animal animal = 1;
  optional string breed = 2;
}

在这里,狗包含动物,因此包含动物的所有信息。

如果您不需要支持向下转换,这种方法就可以工作。也就是说,你永远不必说“这是一只动物吗?”因此,任何可能需要访问狗字段的东西都需要将狗作为输入,而不是动物。对于许多用例,这很好。

message Animal {
  optional string name = 1;
  optional int32 age = 2;

  // Exactly one of these should be filled in, depending on the species.
  optional Dog dog = 100;
  optional Cat cat = 101;
  optional Axolotl axolotl = 102;
  // ...
}

在这种方法中,给定一种动物,您可以找出它是哪种动物,并访问特定物种的信息。也就是说,你可以向下投射。

如果您有一个固定的“子类”列表,这很有效。只需列出所有它们,并记录只应填写其中一个字段。如果有很多子类,您可能需要添加一个枚举字段来指示存在哪个,这样您就不必单独检查has_dog()has_cat()has_mouse()、...

message Animal {
  optional string name = 1;
  optional int32 age = 2;
  extensions 100 to max;  // Should contain exactly one "species" extension.
}

message Dog {
  optional string breed = 1;
}

extend Animal {
  optional Dog animal_dog = 100;
  // (The number must be unique among all Animal extensions.)
}

此选项实际上在语义上与选项#2相同!唯一的区别是,不是在动物中声明许多可选字段,而是将它们声明为扩展。每个扩展名有效地向动物添加了一个新字段,但您可以在其他文件中声明它们,因此您不必有一个中心列表,其他人可以添加新扩展名而无需编辑您的代码。由于每个扩展的行为就像一个常规字段,除了有一些奇怪的语法来声明和访问它之外,所有的行为都与选项#2相同。(事实上,在这里的示例中,导线编码甚至是相同的,因为我们使用100作为分机号,而在选项2中,我们使用100作为字段号。)

这就是理解扩展的诀窍。许多人感到困惑,因为他们试图在面向对象语言中将“扩展”等同于继承。不要那样做!请记住,扩展的行为就像字段一样,这里的选项2和3实际上是相同的。这不是继承。。。但它可以解决同样的问题。

 类似资料:
  • 问题内容: 我想在python中创建一个高效的循环缓冲区(目标是取缓冲区中整数值的平均值)。 这是使用列表收集值的有效方法吗? 什么会更有效(为什么)? 问题答案: 我会用一个arg 在文档中有一个与您想要的菜谱相似的菜谱。我断言它是最有效的,这完全取决于它是由C语言实现的,这是由一个熟练掌握了一流代码的技术人员组成的。

  • 问题内容: 我一直在详尽搜索Google,但是找不到。也许我缺少明显的东西。谢谢! (这是因为预览回调(即使使用缓冲区)的Java实现效率也很低。) 问题答案: 我对这个话题做了一些调查。该演讲(来自第277页,中文)很有帮助。 相机预览通话链 如其他人所述,您可以使用方法获得缓冲区。 这是那里发生的情况(详细版本): 用户调用这是一个本机函数。 调用C ++ 类的方法。 调用接口方法 使一个远程

  • 问题内容: 在编写用于OpenGL库的Matrix类时,我遇到了一个问题,即使用Java数组还是使用Buffer策略存储数据(JOGL为Matrix操作提供直接缓冲区复制)。为了对此进行分析,我编写了一个小型性能测试程序,该程序比较了Arrays vs Buffers和Direct Buffers上循环和批量操作的相对速度。 我想在这里与您分享我的结果(因为我发现它们很有趣)。请随时发表评论和/或

  • 上一章讲的东西比较多,完全理解会有点难,所以这一章来点容易的。我们已经学习了如何定义本地缓冲区的映射和设置选项,现在以同样的方式来学习本地缓冲区的缩写。 打开你的foo和bar这两个文件,切换到foo,然后执行下面的命令: :::vim :iabbrev <buffer> --- &mdash; 在文件foo下进入插入模式输入下面的文本: :::text Hello --- world. Vi

  • 问题内容: 目前,我有一个RESTful Web服务,其端点通过Jersey / JAX-RS公开: 我使用Jackson将POJO序列化/反序列化为JSON,并且我的服务既响应也将POJO发送回。 我现在正在寻找可能使用Google协议缓冲区(或等效技术)来帮助压缩/优化客户端与服务之间的通信的方法,因为JSON /文本非常笨重/浪费。 实际上,我有一个由“微服务”体系结构组成的大型后端。数十种

  • 我有一个要求,我需要保存/缓冲在通道上接收到的消息,并根据消息数量或超时意味着1分钟内没有接收到消息而持久化在数据库中。有没有办法在Spring集成中实现这一点