扩展 (仅用于proto2)

注:内容翻译自官网参考文档中 Java Generated Code 的 Extensions 一节。

假设有一个消息带有扩展范围:

message Foo {
    extensions 100 to 199;
}

protocol buffer编译器将让 Foo 继承 GeneratedMessage.ExtendableMessage 而不是通常的 GeneratedMessage. 类型的, Foo的builder将继承 GeneratedMessage.ExtendableBuilder 。你应该从不通过名字来引用这些基本类型(GeneratedMessage 被认为是实现细节)。然而,这些超类定义了一些额外的方法让你可以用来操作扩展。

尤其 Foo 和 Foo.Builder 将继承方法 hasExtension(), getExtension() 和 getExtensionCount()。此外, Foo.Builder 将继承方法 setExtension() 和 clearExtension()。每个这些方法都将获取一个扩展标识符(下面描述),作为它们的第一个参数,用来标记一个扩展字段。剩下的参数和返回值和为同样类型的普通(非扩展)字段而生成的那些对应的访问器方法完全相同。

给出一个扩展定义:

extend Foo {
    optional int32 bar = 123;
}

protocol buffer 编译器生成一个名为 bar 的"扩展标识符",可以和 Foo的扩展访问器一起使用来访问这个扩展,像这样:

Foo foo =
    Foo.newBuilder()
     .setExtension(bar, 1)
     .build();
assert foo.hasExtension(bar);
assert foo.getExtension(bar) == 1;

(扩展标识符的确切实现非常复杂而且涉及到范型的不可意思的(magical)的使用 - 不过,在使用时你不用担心扩展标识符是如何工作。)

注意 bar 将被声明为.proto文件的outer class的静态字段, 如 前面描述 的。在这个例子中,我们忽略了outer class 的名字。

扩展可以内嵌在其他类型中申明。例如,通用模式是这样:

message Baz {
    extend Foo {
        optional Baz foo_ext = 124;
    }
}

在这个案例中,扩展标识符 foo_ext 内嵌在 Baz 中声明。它可以像下面这样使用:

Baz baz = createMyBaz();
Foo foo =
    Foo.newBuilder()
    .setExtension(Baz.fooExt, baz)
    .build();

当解析一个可能有扩展的消息时,必须提供一个 ExtensionRegistry ,在这里已经注册了需要能够解析的任何扩展。否则,那些扩展将被当成未知字段。例如:

ExtensionRegistry registry = ExtensionRegistry.newInstance();
registry.add(Baz.fooExt);
Foo foo = Foo.parseFrom(input, registry);

results matching ""

    No results matching ""