Googleプロトコルバッファー:ポリモーフィズム、検索

この記事は2つの部分で構成されています。 最初の部分には、 protobufの多型に関する記事の無料の改定が含まれています。 2番目の部分は、フレームワークを操作するための自作の「自転車」の迷惑な広告に専念しています。



更新 :コメントで正しく指摘されているように、継承とポリモーフィズムを1つのパイルに混在させました。 非常に重大なエラーを削除して新しいエラーを追加するには、テキストを少し変更しました。 したがって、一部のコメントがテキストに関連していないように思われる場合は、おそらく以前のバージョンを指しているだけです。 ご不便をおかけして申し訳ありません。




NB :この記事 、「Googleプロトコルバッファーとは」という質問に答えておらず 、特定のプログラミング言語に関係していません。




だから、問題の声明:









NB:ここでは、英語のメッセージの代わりに、「メッセージ」という単語または「構造」という単語が使用されます。 一部の文では、「メッセージ」という言葉は奇妙に聞こえます。




パートI:ポリモーフィズム



プロトコルにSquare、Circle、Polygonの3つのクラスのオブジェクトが含まれているとします。 また、すべてにカラーフィールドとidフィールドがあるとします。 この場所では、Shapeの共通の祖先からそれらを継承し、 目的のポリモーフィズム(または、少なくとも、ベースタイプを使用してオブジェクトを参照する機能)を取得するいくつかの理由があります。 そして、おそらく、継承をサポートする言語で記述した場合、コードは次のようになります。

擬似コード
enum Color { RED, GREEN, BLUE } struct Point { int x; int y; } struct Shape { int id; Color color; } struct Square extends Shape { Point corner; int width; } struct Circle extends Shape { Point center; int radius; } struct Polygon extends Shape { Point [] points; }
      
      









残念ながら、Googleプロトコルバッファは階層をサポートしていません。 Jon Parise 、この制限に対する3つの回避策を検討しています。



オプションのフィールドを使用する


このアプローチでは、後継クラスごとに個別の構造を作成し、Shape構造には各ケースのオプションフィールドが含まれます。

このアプローチには、いくつかの重大な欠点があります。



geom-1.proto
  enum Color { RED = 1; GREEN = 2; BLUE = 3; } message Point { required fixed32 x = 1; required fixed32 y = 2; } message Square { required Point corner = 1; required fixed32 width = 2; } message Circle { required Point center = 1; required fixed32 radius = 2; } message Polygon { repeated Point points = 1; } message Shape { required TYPE type = 1; required fixed32 id = 2; optional Color color = 3; //  optional Square square = 4; optional Circle circle = 5; optional Polygon polygon= 6; }
      
      









ネストされたシリアル化


別のアプローチでは、相続人に共通のフィールドを持つShape構造を作成し、相続人のシリアル化されたフィールドが既にある別のフィールドを追加します。



また、「シリアライザー」はサブクラスフィールドの内容を自動的に「アンパック」しないため、これは最も成功したオプションではありません。したがって、整合性チェックは実行されません。

とにかく、それは何とか美しくありません。

geom-2.proto
  enum TYPE { SQUARE = 1; CIRCLE = 2; POLYGON = 3; } enum Color { RED = 1; GREEN = 2; BLUE = 3; } message Point { required fixed32 x = 1; required fixed32 y = 2; } message Square { required Point corner = 1; required fixed32 width = 2; } message Circle { required Point center = 1; required fixed32 radius = 2; } message Polygon { repeated Point points = 1; } message Shape { required TYPE type = 1; required fixed32 id = 2; optional Color color = 3; //  required bytes subclass = 4; }
      
      









ネストされた拡張機能


3番目(推奨)のアプローチは最初のアプローチと似ていますが、オプションのフィールドの代わりにネストされた拡張機能が使用されます。 四角い円と戦うために、タイプフィールドが入力されます。

geom-final.proto
  enum TYPE { SQUARE = 1; CIRCLE = 2; POLYGON = 3; } enum Color { RED = 1; GREEN = 2; BLUE = 3; } message Point { required fixed32 x = 1; required fixed32 y = 2; } message Shape { required TYPE type = 1; required fixed32 id = 2; optional Color color = 3; extensions 4 to max; } message Square { extend Shape { required Square shape = 5; } required Point corner = 1; required fixed32 width = 2; } message Circle { extend Shape { required Circle shape = 6; } required Point center = 1; required fixed32 radius = 2; } message Polygon { extend Shape { required Polygon shape = 7; } repeated Point points = 1; }
      
      







このアプローチの利点を詳しく見てみましょう。





パートII:検索



そのため、メッセージ構造の説明を含むファイル(geom.proto)があります。 私たちのプログラムは機能し、メッセージ自体を含む大きなファイルを作成しました。 その中に必要な情報を見つけたいのですが、これは単純なテキスト検索では常に可能とは限りません。



例:



同意して、通常のgrepはここでは役に立ちません。



もちろん、そのようなタスクごとに小さなプログラムを書くのは簡単で、指定されたプロパティを持つファイル内の数字を探します。 ただし、構造化されたデータとその形式があるため、独自のクエリ言語を作成してみませんか?



タスクの例を返します。





これだけでなく、はるかに多くが自作の自転車を作ることができます。



また、彼はできる
  • ファイルをバイナリ形式からテキスト形式に、またはその逆に転送します
  • メッセージから特定のフィールドのみを切り取り、印刷します
  • 1つの要求で複数の連続したメッセージを使用します。 たとえば、円の直後にあるすべての正方形を見つけます。






自転車がユーザーを見つけ、それとともに自転車の構文と機能に関する詳細なトピックが必要になることを願っています。

ありがとう



All Articles