Main Content

オブジェクト指向の設計を使用する理由

MATLAB プログラムを記述する方法

ソフトウェア アプリケーションを作成する場合、一般には、アプリケーション データを設計し、そのデータに対して行う操作を実装します。手続きプログラミングでは、必要な操作をデータに実行する関数に、データを渡します。オブジェクト指向ソフトウェアは、オブジェクトのインターフェイスによって互いにやり取りする、データとオブジェクトへの操作をカプセル化します。

MATLAB® 言語では、手続き型の手法やオブジェクト指向の方法を使用してプログラムを作成でき、プログラム内でオブジェクトと通常の関数を一緒に使用できます。

手続き型プログラムの設計

手続き型プログラミングの設計では、目的の状態を達成するために実行しなければならないステップに重点が置かれます。データは通常、構造体の個体変数またはフィールドとして表されます。各種操作は、変数を引数として受け取る関数として実装されます。プログラムは、通常、データを受け取る一連の関数を呼び出し、変更したデータを返します。個々の関数は、データに 1 つの操作、あるいは多数の操作を実行します。

オブジェクト指向プログラムの設計

オブジェクト指向プログラムの設計には、以下が含まれます。

  • ビルドするシステムやアプリケーションのコンポーネントの特定

  • どのコンポーネントが繰り返し使用されるか、または特性を共有するかを決めるための、パターンの解析と特定

  • 類似と相違に基づくコンポーネントの分類

このような分析を行ってから、ユーザー アプリケーションが使用するオブジェクトを記述するクラスを定義します。

クラスとオブジェクト

クラスは、共通の特性をもつオブジェクトのセットを記述します。オブジェクトは、クラスの特定的なインスタンスです。あるオブジェクトを同じクラスの他のオブジェクトと区別させるものは、オブジェクトのプロパティに含まれる各種の値です。クラス定義の関数 (メソッドと呼ばれる) とは、あるクラスのすべてのオブジェクトに共通するオブジェクトの動作を実装するものです。

オブジェクト指向プログラムを作成するタイミング

簡単なプログラミングのタスクを単純な関数として実装できます。ただし、ユーザーのタスクの規模や複雑さが増すにつれて、関数の管理はさらに複雑で困難になります。

関数が非常に大規模になると、関数をより小さな関数に分割し、ある関数から他の関数にデータを渡すことになります。ただし、関数の数が多くなると、関数に渡されるデータの設計と管理が困難になり、エラーが発生しやすくなります。この時点で、MATLAB プログラミング タスクをオブジェクト指向の設計に移行することを検討してください。

問題をオブジェクトの点から理解する

問題によっては、オブジェクトの点から考えると、より自然で、より簡単になります。問題のステートメントにおいて、名詞は、定義するオブジェクトとして、さらに、動詞は、実行する操作として考えられます。

融資機関 (銀行、住宅金融専門会社、独立系の融資業者など) を表すクラスの設計を考えてみます。さまざまな種類の融資業者を手続きとして表すのは困難です。ただし、それぞれの融資業者は、特定のアクションを実行し、特定データを含むオブジェクトとして表すことができます。オブジェクトを設計する過程では、ユーザー アプリケーションにとって重要な、融資業者の特徴を明確にすることが必要になります。

共通点の特定.  すべての融資業者に共通な点は何でしょうか。たとえば、すべての MoneyLender オブジェクトは 1 つの loan メソッドと 1 つの InterestRate プロパティをもつことができます。

相違点の特定.  それぞれの融資業者はどのように異なるでしょうか。企業への融資が可能な業者もあれば、個人への融資のみを行う業者もあります。したがって、loan の操作は、融資機関の種類が異なれば違うものにする必要があるかもしれません。基底の MoneyLender クラスをサブクラス化することで、loan メソッドのサブクラス バージョンを特化できます各融資業者は、その InterestRate プロパティに異なる値をもつことができます。

共通点をスーパークラスに括り出し、融資業者ごとに固有な点をサブクラスに実装します。

必要なものだけを追加.  これらの機関は、ユーザー アプリケーションにとって重要ではない多くの活動と関連する可能性があります。設計フェーズでは、問題定義に基づいて、オブジェクトにどのような操作とデータを含めなければならないかを決定します。

オブジェクトによる内部状態の管理

オブジェクトは、構造体や cell 配列からでは使用できない、いくつかの有用な特性を提供します。たとえば、オブジェクトでは以下が可能です。

  • 任意の指定プロパティへの代入データ値の制限

  • プロパティ値のクエリ発生時にのみこれを計算

  • プロパティ値のクエリまたは変更時に通知をブロードキャスト

  • プロパティやメソッドへのアクセスの制限

冗長性の削減

オブジェクト指向設計の利点は、ユーザー プログラムの複雑さが増すほど明らかになります。たとえば、ユーザー アプリケーションの一部として、次の手続きを実装するとします。

  1. 入力をチェックする

  2. 最初の入力引数に対して計算を実行する

  3. 第 2 入力引数に基づき、手順 2 の結果を変換する

  4. 出力の有効であることをチェックして値を返す

この手続きは通常の関数として実装できます。しかし、手順 2 では異なる計算を実行する必要があるものの、ユーザー アプリケーションのどこかで再び、この手続きを使用するものとします。最初の実装をコピーして貼り付けた後に手順 2 を書き換えることができます。あるいは、どの計算を行うかを示すオプションを受け入れる関数を作成することもできます。しかし、これらのオプションによってコードの複雑さは増します。

オブジェクト指向の設計では、共通のコードを基底クラスと呼ばれるクラスに括り出すことができます。基底クラスは、使用するアルゴリズムを定義し、このコードを使用するすべてのクラスに共通するものを実装します。手順 2 は構文的に定義されますが実装はされず、この基底クラスからその後の派生クラスへの特化された実装はされないままになります。

手順 1

function checkInputs()
   % actual implementation
end

手順 2

function results = computeOnFirstArg()
   % specify syntax only
end

手順 3

function transformResults()
   % actual implementation
end

手順 4

function out = checkOutputs()
   % actual implementation
end

基底クラスのコードがコピーされたり変更されたりすることはありません。この基底クラスから派生させたクラスはこのコードを継承します。継承はテスト対象コードの量を減らし、基本的な手続きにおける変更からユーザー プログラムを分離します。

統一性のあるインターフェイスを定義する

より特化したクラスの基本として、類似しているクラスを使用することは、オブジェクト指向プログラミングでの有効な手法です。このクラスは共通のインターフェイスを定義します。このようなクラスをユーザー プログラムの設計に組み込むと、以下のことが可能になります。

  • 特定の目的のための要件を確認する

  • 要件をインターフェイス クラスとしてプログラム内でコード化する

複雑さの低減

オブジェクトは、コンポーネントやシステムを使用するために知っていなければならないことを減らすことで、複雑度を低減します。

  • オブジェクトによる、実装の詳細を非表示にするインターフェイスの提供

  • オブジェクトによる、オブジェクト間対話における制御ルールの実効性付与

これらの利点を説明するために、二重連結リストと呼ばれるデータ構造の実装を考えます。実際の実装については、クラスによる連結リストの実装を参照してください。

3 要素から成るリストの図を以下に示します。

リストにノードを追加するには、リスト内の既存のノードを切断し、新規ノードを挿入して適切に再接続します。基本手順を次に示します。

始めに、ノードを切断します。

  1. n1 から n2.Prev を外します。

  2. n2 から n1.Next を外します。

ここで、新しいノードを作成して接続し、元のノードに番号を付け直します。

  1. n1new.Prev を連結します。

  2. n3 (n2 でした) に new.Next を連結します。

  3. new (n2 になります) に n1.Next を連結します。

  4. new (n2 になります) に n3.Prev を連結します。

メソッドがこれらの手順を実行する方法の詳細は、クラスの設計においてカプセル化されています。各 node オブジェクトには、それ自体をリストに挿入したり、リストから削除する機能が含まれています。

たとえば、このクラスでは、node オブジェクトはそれぞれ insertAfter メソッドをもちます。リストにノードを追加するには、node オブジェクトを作成してから、そのオブジェクトの insertAfter メソッドを呼び出します。

nnew = NodeConstructor;
nnew.insertAfter(n1)

ノード クラスがこれらの操作を実装するコードを定義することから、このコードは、

  • クラスの作成者により最適な方法で実装される

  • 現在のバージョンのクラスで常に最新

  • 適切にテスト済み

  • 旧バージョンのオブジェクトが MAT ファイルから読み込まれた場合は、自動更新が可能

オブジェクト メソッドは、ノードが相互に作用する方法についてのルールを強制的に適用します。この設計により、オブジェクトを使用するアプリケーションでルールを強制する必要がなくなります。これは、さらに、プロセスのそれ自身の実装において、アプリケーションがエラーを生成する可能性が減ることも意味します。

モジュール化の促進

システムをオブジェクト (自動車 –> エンジン –> 燃料供給装置 –> 酸素センサー) に分解すると、自然な境界にしたがってモジュールを形成することになります。クラスは、コードのモジュール化に関し、3 つのレベルのコントロールを提供します。

  • パブリック — 任意のコードがこの特定のプロパティにアクセスでき、このメソッドを呼び出せます。

  • 保護 — このオブジェクトのメソッドと、このオブジェクトのクラスから派生したオブジェクトのメソッドのみが、このプロパティにアクセスし、このメソッドを呼び出すことができます。

  • プライベート — オブジェクト自体のメソッドのみが、このプロパティにアクセスし、このメソッドを呼び出すことができます。

オーバーロードされる関数と演算子

クラスを定義する場合、新しいオブジェクトに機能する、既存の MATLAB 関数をオーバーロードできます。たとえば、MATLAB シリアル ポート クラスは、関数 fread をオーバーロードして、このオブジェクトが表すポートに接続したデバイスからデータを読み込みます。データを表すために定義したクラスに対して、等式 (eq) または加算 (plus) などのさまざまな演算を定義できます。

関連するトピック