如何使用原型缓冲区有效地完成继承 [英] How to accomplish inheritance effectively using proto-buffers

查看:116
本文介绍了如何使用原型缓冲区有效地完成继承的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有基类消息

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

以及扩展动物的子类

message Dog{
     optional string breed = 1;
}

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

So while building a dog message , i should be able to set all the fields of Animal. I know the round about way of doing it (declaring all the animal fields once again in dog message)but is it possible simply and effectively using protobuffers? Also i learnt about extensions and i understood that it is just used to add a new field to the already existing message and so it should not be misconstrued to be the possible solution for achieving inheritance.

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

Is it possible to achieve the above simple design using protobuffers's extensions?

推荐答案

在Protocol Buffers中有几种​​不同的方法可以完成继承。你想要哪一个取决于你的用例。

There are a few different ways to accomplish "inheritance" in Protocol Buffers. Which one you want depends on your use case.

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

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

此处,包含 Animal ,因此包含 Animal 的所有信息。

Here, Dog contains an Animal, thus contains all the information of Animal.

如果您不需要支持向下转换,则此方法有效。也就是说,你永远不必说这是动物一个?因此,任何可能需要访问 Dog 字段的内容都需要以 Dog 作为输入,而不是动物。对于许多用例,这很好。

This approach works if you do not need to support down-casting. That is, you never have to say "Is this Animal a Dog?" So, anything which might need to access the fields of Dog needs to take a Dog as its input, not an Animal. For many use cases, this is fine.

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

在这种方法中,给出一个动物,你可以弄清楚它是哪种动物并获取物种特定的信息。也就是说,你可以向下转换。

In this approach, given an Animal, you can figure out which animal it is and access the species-specific information. That is, you can down-cast.

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

This works well if you have a fixed list of "subclasses". Just list all of them, and document that only one of the fields should be filled in. If there are a lot of subclasses, you might want to add an enum field to indicate which one is present, so that you don't have to individually check 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相同!唯一的区别是,不是在 Animal 中声明大量可选字段,而是将它们声明为扩展名。每个扩展都有效地将新字段添加到 Animal ,但您可以在其他文件中声明它们,因此您不必拥有一个中央列表,而其他人可以添加新的扩展而无需编辑代码。由于每个扩展的行为就像常规字段一样,除了用于声明和访问它的语法有些奇怪之外,所有内容都与选项#2的行为相同。 (事实上​​,在这里的示例中,线编码甚至是相同的,因为我们使用100作为分机号码,而在选项2中我们使用100作为场号。)

This option is actually semantically identical to option #2! The only difference is that instead of declaring lots of optional fields inside Animal, you are declaring them as extensions. Each extension effectively adds a new field to Animal, but you can declare them in other files, so you don't have to have one central list, and other people can add new extensions without editing your code. Since each extension behaves just like a regular field, other than having somewhat-weird syntax for declaring and accessing it, everything behaves the same as with option #2. (In fact, in the example here, the wire encoding would even be the same, since we used 100 as the extension number, and in option 2 we used 100 as the field number.)

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

This is the trick to understanding extensions. Lots of people get confused because they try to equate "extend" to inheritance in object-oriented languages. Don't do that! Just remember that extensions behave just like fields, and that options 2 and 3 here are effectively the same. It's not inheritance... but it can solve the same problems.

这篇关于如何使用原型缓冲区有效地完成继承的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆