1CのOOPは自分で行います。 クラスとオブジェクトを模倣する方法、およびそれが必要な理由

画像



1Cでのオブジェクト指向プログラミングの使用方法についてお話ししたいと思います。 むしろ、その模倣、なぜなら 最も埋め込まれた言語では、そのような機能はありません。 それにもかかわらず、論理的に独立した分離された自己完結型のコードフラグメントを作成する機能(およびデータがカプセル化されている場合でも)は非常に便利です。



結局のところ、彼らは次のことができます:



-同じプロジェクト内で再利用。

-1つのプロジェクトから別のプロジェクトに簡単に(考えずに)転送できます。

-特定の問題を解決するための独立した手段として一般的に使用するために、他の誰かにそれを渡すか、誰かに簡単にコピーして自分のプロジェクトに貼り付けることができます);

-クラスがあれば、複数のオブジェクトを一度に作成できます(それらから配列、コレクション、リストなどを作成します)。

-私が知らない他のいくつかのプラス...



この記事では、手続き指向の1C言語を使用してOOPをシミュレートする手法を示します。



問題の本質



ご存知のように、組み込みの1C言語はOOPを完全にはサポートしていません。 フィールド、プロパティ、メソッドを備えた標準の組み込みプラットフォームクラスがあります。 これらのクラスのオブジェクトを作成できます。



 =  ;
      
      





通常のユニバーサルプログラミング言語で行われている方法で使用します。 ただし、組み込み言語で独自のクラスを定義および実装することはできません。 原則として、1Cプラットフォームはオブジェクト指向プログラミングをサポートしていないと言えます。



さらに、1Cの専門家数人から、このようなサポートはまったく不要であると聞きました。 しかし、これらはまさに「1Cプログラマー」でした。 コンピューターではなく1Cプラットフォームのみの開発に常に携わっており、古典的な「コンピューターサイエンス」に精通していない人々。 通常のユニバーサル言語で開発に携わっており、1Cプラットフォームに直面しているOOP機能に慣れている人は、多くの場合、プログラムのアーキテクチャを構築できないことから深刻な不便を経験し、一般に自分の考え、タスクの実装のビジョンをオブジェクトモデルの形で表現します。 OOPの代わりに、組み込み言語は構造プログラミングに戻ります。これも、従来のバージョン(たとえば、PascalおよびC言語)と比較して短縮されています。 1つまたは別の構成オブジェクトで、一般的なフォーム(フォームなし)のモジュールを複数作成することはできません。 これは、たとえば、外部処理を実行する場合(特定の構成に結び付けられないようにするため、または通常の構成自体に変更を加えてサポートから削除したくない場合)、したがって、処理の一部を「共通モジュール」に転送できない場合、非常に重要です-すべての機能を単一の処理モジュールに配置する必要があります。 別のモジュール内の特定のモジュールを接続する方法はありません( uses句または#include句)。



 Uses , ; #include .;
      
      





ただし、この記事はモジュールに関するものではありません。



それでは、構造プログラミングツールを使用して、主要なOOPパラダイムの少なくとも一部をどのように実装できますか?



ポリモーフィズムとタイププロパティを使用



 property MyVar: Integer read GetMyVar write SetMyVar;
      
      





何も出力されません(実際に実行することもできますが、構文的にはだまされすぎて、く、したがって不便で使用中に明らかではありません)。 アクセス制御( privateprotectedpublic )についても忘れる必要があります。 ただし、カプセル化と継承( パブリックアクセスモードで)は非常にうまく行うことができます。



決定の本質



この考え方は一般的に新しいものではなく、たとえば、 GTK +グラフィックスライブラリなどのUnixの世界の強力なスーパープロジェクトのアーキテクチャで収集できます。 このライブラリはC言語で実装されていますが、そのアーキテクチャの事実により、オブジェクト指向です(上記のWikipediaの記事からGTK +ライブラリを初期化する例を参照してください-それが意味するところから明らかになります)。 OOPがサポートしていない言語を使用してOOPを実装する機能は、ソースコーディングに関する特別な合意の採用にあります。



結局のところ、クラスとは何ですか? クラスとは、データとその処理方法を「1つのボトル」で定義したものです。 実際、オブジェクトは動的に作成されたデータセットであり、暗黙的にパラメーターとしてクラスメソッドに渡され、メソッドがこのデータを処理できるようにします。 そして、言語、データ、およびメソッドを「単一ボトル」にプッシュできない場合、言語の機能に条件付きアドオンを使用します-コード規約。



オブジェクトのフィールドのストレージとして構造を使用します(Cでは、これは組み込みのデータ型であり、1Cでは、組み込みクラス、ハッシュテーブルです)。



  =  ; . («1», 0); . («2», “”); … . («N»,  );
      
      





メソッドとして、次の命名規則を使用してプロシージャと関数を使用します。



  _(, …);  _(, …);
      
      





ご覧のように、ポインターパラメーターをオブジェクトのフィールドセットに暗黙的に渡すのではなく、1番目のパラメーターとして明示的に渡されます。 次に、メソッドパラメータの通常のセットがあります。



次の例を考えてみましょう。



郵便局クラスの例
 //////////////////////////////////////////////////////////////////////////////// //    //      . // // : // . // : //    //  _()  //       ,   //    ,  , //   ,       //  ,    , // ..    ( )  //   .  =  ; //    .("", ); //    .("", _()); //     ;  //   . // // : //  -      //  -   ,    // : // () -     //  _(, )  //    = _(); //    . = ; _Assign(., );  ;  //    -  . // // : //  -    //  _()  //           1. //       -  . // :     . _(.);  //     . // // : //  -    // : // () -     //  _()   = . + ", " + _(.);  ;  //////////////////////////////////////////////////////////////////////////////// //    //      . // // : // . // : //    //  _()   =  ; //    .("", ); //   .("", ); //   .("", ); //   .("", ); //    ;  //   . // // : //  // : // () -     //  _()  //    = _();  ;  //    -  . // // : //  -    //  _()   //    . // // : //  -    //  -   //  -   //  -   //  -   //  _(, , , , )  . = ; . = ; . = ; . =   //    . // // : //  -    // : // () -    //  _()   = . + ", " + ". " + . + ", " + ". " + . + ", " + ". " + .;  ;  //     2   1. //    1  . // // : // 1 -     // 2 -    -  //  _Assign(1, 2)  1. = 2.; 1. = 2.; 1. = 2.; 1. = 2. 
      
      







これはカプセル化の例です。 継承はもう少し不器用に見えます。



クラス:直線、直線、円周
 //////////////////////////////////////////////////////////////////////////////// //    //      . // // : // . // : //    //  _()   =  ; //    .("X1", 0); // X-  .("Y1", 0); // Y-   ;  //   . // // : // X1, Y1 -   ()   // : // () -     //  _(X1, Y1)  //    = _(); //    .X1 = X1; .Y1 = Y1;  ;  //    -  . // // : //  -    //  _()   //   . // // : //  -    // X1, Y1 -   ()   //  _(, X1, Y1)  .X1 = X1; .Y1 = Y1;  //   . // // : //  -    // : // () -   //  _()   0; //  -         //////////////////////////////////////////////////////////////////////////////// //    -   . //      . // // : // . // : //    //  _()   = _(); //    .("X2", 0); // X-   .("Y2", 0); // Y-    ;  //   . // // : // X1, Y1 -     // X2, Y2 -     // : // () -     //  _(X1, Y1, X2, Y2)  //    = _(); //    _(, X1, Y1, X2, Y2);  ;  //    -  . // // : //  -    //  _()   //   . // // : //  -    // X1, Y1 -     // X2, Y2 -     //  _(, X1, Y1, X2, Y2)  _(, X1, Y1); .X2 = X2; .Y2 = Y2;  //   . // // : //  -    // : // () -   //  _()  //       X X = .X2 - .X1; //       Y Y = .Y2 - .Y1; //       = Sqrt(X*X + Y*Y);  ;  //////////////////////////////////////////////////////////////////////////////// //    () -   . //      . // // : // . // : //    //  _()   = _(); //    .("R", 0); //    ;  //   . // // : // X, Y -    // R -   // : // () -     //  _(X, Y, R)  //    = _(); //    _(, X, Y, R);  ;  //    -  . // // : //  -    //  _()   //   . // // : //  -    // X, Y -    // R -   //  _(, X, Y, R)  _(, X, Y); .R = R;  //   . // // : //  -    // : // () -   //  _()   = 2*3.14*.R;  ; 
      
      







当然、ここには仮想的なメソッドやポリモーフィズムはありません。 子孫での同じ名前のメソッドの再定義のみ。 開発ロジックの観点からは、同じ名前です。



まとめ



ご覧のとおり、1C言語でソースコードを設計するために説明した手法は、このように記述されたコードフラグメントの可能性を、視覚化、普遍性、移植性の観点から拡張します。



将来の出版物では、すぐにそれらの1Cプログラムで使用できるいくつかの有用なもの(あなたが言うことができるツール)について話すつもりです。 それらのコードは、そのようなクラスの形式でのみ発行されます。



記事(1C 8.2の処理) 検討されている例のテキストをここからダウンロードします



皆さん、頑張ってください。 じゃあね



PS:この記事を準備する過程で、 Infostartポータルで同様のアプローチの説明に出会いました。 2012年に書かれたようです-ほぼ同時にこの方法を使い始めました。 この記事には大きな違いがあるため(著者はメソッド呼び出しの統合とラッパー関数を介したクラスプロパティへのアクセスを提案していますが、これは技術的に高度ですが、私の意見ではあまりわかりません)、独自のバージョンの技術を公開することにしました。



All Articles