Наследование в буферах протокола
Как обрабатывать наследование в 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;
}
2 ответа
Протокол Буферы не поддерживает наследование. Вместо этого рассмотрите возможность использования композиции:
message Foo {
Bar bar = 1;
string id = 2;
}
Тем не менее, вы можете использовать хитрость, которая похожа на наследование, но которая является уродливым взломом, поэтому вы должны использовать ее только с осторожностью. Если вы определяете ваши типы сообщений, такие как:
message Bar {
string name = 1;
}
message Foo {
string name = 1;
string id = 2;
}
Эти два типа совместимы, потому что Foo
содержит надмножество полей Bar
, Это означает, что если у вас есть закодированное сообщение одного типа, вы можете декодировать его как другой тип. Если вы попытаетесь расшифровать Bar
как тип Foo
, поле id
не будет установлен (и получит значение по умолчанию). Если вы декодируете Foo
как тип Bar
, поле id
будут игнорироваться (Обратите внимание, что это те же правила, которые применяются при добавлении новых полей в тип с течением времени.)
Вы можете использовать это для реализации чего-то вроде наследования, имея несколько типов, каждый из которых содержит копию полей "суперкласса". Однако есть несколько больших проблем с этим подходом:
- Чтобы преобразовать объект сообщения типа
Foo
печататьBar
Вы должны сериализовать и повторно проанализировать; ты не можешь просто бросить. Это может быть неэффективно. - Очень трудно добавить новые поля в суперкласс, потому что вы должны убедиться, что добавили поле в каждый подкласс, и убедиться, что это не создает никаких конфликтов номеров полей.
См. Учебник Основы протокола буфера:
Не ищите средств, похожих на наследование классов, но буферные протоколы этого не делают.