我有动物猫和狗的消息,但是如果我创建一个对象,我不知道如何设置猫的声明或狗的bones_buried字段。 我想创建一个Cat,并从中创建一个动物对象。
message Animal {
extensions 100 to max;
enum Type {
Cat = 1;
Dog = 2;
}
required Type type = 1;
}
message Cat {
extend Animal {
required Cat animal = 100;
}
optional bool declawed = 1;
}
message Dog {
extend Animal {
required Dog animal = 101;
}
optional uint32 bones_buried = 1;
}
我的测试类:
public class Test {
public static void main(String[] args) {
Animal.Builder animal = Animal.newBuilder().setType(Animal.Type.Cat);
Cat c = animal.getExtension(Cat.animal);
Cat cat = Cat.newBuilder().setDeclawed(true).build();
// animal = cat!
Animal a = animal.build();
}
}
答案 0 :(得分:1)
小心! Protobuf扩展是不是子类。它们有时可以用作继承的替代品,但它们与继承的工作方式完全不同。例如,您的Animal
类型实际上可以同时 一个Cat
和一个Dog
扩展名。
扩展实际上表现得像字段一样。每次extend Animal
时,您实际上都会向Animal
消息添加新字段。换句话说,你的proto实际上相当于:
message Animal {
enum Type {
Cat = 1;
Dog = 2;
}
required Type type = 1;
optional Cat cat = 100;
optional Dog dog = 101;
}
message Cat {
optional bool declawed = 1;
}
message Dog {
optional uint32 bones_buried = 1;
}
唯一的区别是扩展可以在它们正在扩展的消息之外声明。
回想起来,我应该使用与“扩展”不同的词来避免与继承混淆。
由于扩展只是字段,因此它们具有与字段访问器等效的访问器。以下是您的代码编写方式:
Animal animal = Animal.newBuilder()
.setType(Animal.Type.Cat);
.setExtension(Cat.animal,
Cat.newBuilder().setDeclawed(true))
.build();
顺便说一下,在您的示例中,您声明了扩展程序required
。实际上这是不允许的 - 永远不需要扩展,因为扩展本质上是可选的。如果实际允许所需的扩展,那么您的proto实际上会声明每个Animal
必须 Cat
和Dog
扩展名。