Nullable な Setter/Getter のサポートなし
一部の人々が、null を許容する言語 (特に Kotlin、C#、Rust) で nullable な getter/setter を Protobuf にサポートしてほしいというフィードバックをいただいています。これはこれらの言語を使用する人々にとって役立つ機能であるように思われますが、この設計上の選択にはトレードオフがあり、その結果、Protobuf チームはそれらを実装しないことを選択しました。
nullable なフィールドを持たない最大の理由は、.proto
ファイルで指定されたデフォルト値の意図された動作です。設計上、設定されていないフィールドで getter を呼び出すと、そのフィールドのデフォルト値が返されます。
注: C# はメッセージフィールドを nullable として扱います。他の言語とのこの矛盾は、不変のメッセージがないことに起因しており、共有の不変のデフォルトインスタンスを作成することが不可能になっています。メッセージフィールドはデフォルト値を持つことができないため、これに機能上の問題はありません。
例として、次の .proto
ファイルを考えてみましょう。
message Msg { optional Child child = 1; }
message Child { optional Grandchild grandchild = 1; }
message Grandchild { optional int32 foo = 1 [default = 72]; }
および対応する Kotlin getter
// With our API where getters are always non-nullable:
msg.child.grandchild.foo == 72
// With nullable submessages the ?. operator fails to get the default value:
msg?.child?.grandchild?.foo == null
// Or verbosely duplicating the default value at the usage site:
(msg?.child?.grandchild?.foo ?: 72)
および対応する Rust getter
// With our API:
msg.child().grandchild().foo() // == 72
// Where every getter is an Option<T>, verbose and no default observed
msg.child().map(|c| c.grandchild()).map(|gc| gc.foo()) // == Option::None
// For the rare situations where code may want to observe both the presence and
// value of a field, the _opt() accessor which returns a custom Optional type
// can also be used here (the Optional type is similar to Option except can also
// be aware of the default value):
msg.child().grandchild().foo_opt() // Optional::Unset(72)
nullable な getter が存在する場合、ユーザーが指定したデフォルト (代わりに null を返す) を必然的に無視することになり、驚くべき矛盾した動作につながります。 nullable な getter のユーザーがフィールドのデフォルト値にアクセスしたい場合、null が返された場合にデフォルトを使用するように独自のカスタム処理を記述する必要があります。これは、null getter を使用したよりクリーンで簡単なコードという想定される利点を損ないます。
同様に、nullable な setter を提供することも、動作が直感的でなくなるため行いません。 set を実行してから get を実行しても、常に同じ値が返されるとは限らず、set を呼び出しても、フィールドの has-bit に影響を与えるのは一部の場合のみです。
メッセージ型のフィールドは常に明示的な存在フィールド (hazer 付き) であることに注意してください。 Proto3 は、スカラーフィールドが明示的に optional
とマークされていない限り、暗黙的な存在 (hazer なし) をデフォルトとしますが、Proto2 は暗黙的な存在をサポートしていません。Editions では、暗黙的な存在機能が使用されない限り、明示的な存在がデフォルトの動作です。 ほとんどすべてのフィールドが明示的な存在を持つという将来の期待により、nullable な getter に伴う人間工学的な懸念は、Proto3 ユーザーにとってそうであったかもしれないよりも大きな懸念になると予想されます。
これらの問題により、nullable な setter/getter はデフォルト値の使用方法を根本的に変更する可能性があります。 可能な有用性は理解していますが、それによってもたらされる矛盾と困難は価値がないと判断しました。