Я определяю сообщение ProtoBuf, в котором я хочу иметь «обнуляемое» поле - т.е. я хочу различать поле, имеющее значение и не имеющее значения. В качестве конкретного примера, скажем, у меня есть поля «x» и «y» для записи координат какого-либо объекта. Но в некоторых случаях координаты неизвестны. Следующее определение будет не работать, потому что если x или y не определены, то по умолчанию они равны нулю (что является допустимым значением):
message MyObject {
optional float x = 1;
optional float y = 2;
}
Один из вариантов - добавить запись логического поля независимо от того, известно значение соответствующего поля или нет. I.e.:
message MyObject {
optional bool has_x = 1; // if false, then x is unknown.
optional bool has_y = 2; // if false, then y is unknown.
optional float x = 3; // should only be set if has_x==true.
optional float y = 4; // should only be set if has_y==true.
}
Но это налагает некоторую дополнительную бухгалтерию - например, когда я устанавливаю значение поля x, я всегда должен не забывать также устанавливать has_x. Другим вариантом может быть использование значения списка с условием, что список всегда имеет длину 0 или 1:
message MyObject {
repeated float x = 1; // should be empty or have exactly 1 element.
repeated float y = 2; // should be empty or have exactly 1 element.
}
Но в этом случае определение кажется немного вводящим в заблуждение, и интерфейс не намного лучше.
Есть ли третий вариант, о котором я не подумал, что он лучше, чем эти два? Как вы справились с хранением пустых полей в protobuf?