MATLAB と他のオブジェクト指向言語との比較
C++ および Java コードとの相違点
MATLAB® プログラミング言語には、C++ や Java® などの他のオブジェクト指向言語と比較するといくつかの重要な相違点があります。
パブリック プロパティ
C++ または Java 言語のフィールドとは異なり、データ ストレージの実装から分離してパブリック インターフェイスを定義するために MATLAB プロパティを使用できます。プロパティ値の割り当てやクエリの実行時に自動的に実行される set および get アクセス メソッドはユーザーが定義できるため、プロパティにパブリック アクセスを指定できます。たとえば、次のステートメント、
myobj.Material = 'plastic';
は char
ベクトル plastic
を myobj
の Material
プロパティに代入しています。実際の割り当てを実行する前に、myobj
は set.Material
と呼ばれるメソッドを実行します (myobj
のクラスがこのメソッドを定義することが前提)。このメソッドは、必要となるすべての演算を実行できます。プロパティ アクセス メソッドの詳細については、プロパティの get メソッドおよび set メソッドを参照してください。
また、プロパティへのアクセスも、パブリック、保護、またはプライベートのアクセスを属性に設定することで制御することができます。プロパティの属性の一覧は、プロパティの属性を参照してください。
暗黙的パラメーターではない
言語によっては、メソッドに対する 1 つのオブジェクト パラメーターは、常に暗黙的です。MATLAB では、オブジェクトは、オブジェクトに作用するメソッドに対するエクスプリシット パラメーターです。
ディスパッチング
MATLAB クラスでは、C++ や Java コードの場合とは異なり、メソッド ディスパッチングがメソッドのシグネチャに基づきません。引数リストに同じ優先順位のオブジェクトが含まれている場合、MATLAB は呼び出すメソッドを選択する際に、最も左にあるオブジェクトを使用します。
しかし、ある引数のクラスが他の引数のクラスよりも上位の場合、MATLAB は引数リストにおける位置とはかかわりなく、上位にある引数のメソッドにディスパッチします。
詳細については、クラスの優先順位を参照してください。
スーパークラス メソッドの呼び出し
C++ では、スコープ演算子、
superclass::method
Java コードでは、
superclass.method
これと等価な MATLAB 演算子は、
です。method@superclass
他の相違点
MATLAB クラスには、C++テンプレートまたは Java ジェネリクスに相当するものはありません。ただし、MATLAB では、複数のデータ型が許され、異なる型のデータに作用する関数やクラスを記述することが可能です。
MATLAB クラスは、異なるシグネチャを使用して同じ関数名でオーバーロードされる関数をサポートしません。
オブジェクトの変更
MATLAB クラスはパブリック プロパティを定義できます。パブリック プロパティは、クラスのインスタンスに値を明示的に割り当てることで変更できます。ただし、handle
クラスから派生したクラスのみが参照の動作を示します。値クラス (handle
から派生しなかったクラス) のインスタンスのプロパティ値を変更すると、変更が行われたコンテキスト内でのみその値が変わります。
次節以降では、この動作について詳しく説明します。
関数に渡されるオブジェクト
MATLAB は、すべての変数を値で渡します。オブジェクトを関数に渡す場合、MATLAB は、呼び出し元の関数の値を呼び出し先の関数のパラメーター変数にコピーします。
ただし、MATLAB では、コピー時に以下の異なる動作を伴う 2 種類のクラスがサポートされています。
ハンドルのクラス — オブジェクトを参照するハンドル クラス インスタンス変数。ハンドル クラス インスタンス変数のコピーは、元の変数と同じオブジェクトを参照します。入力引数として渡されたハンドル オブジェクトが関数によって変更された場合、その変更内容は、元のハンドルとコピーされたハンドルの両方によって参照されるオブジェクトに影響します。
値のクラス — 値のクラスのインスタンスにあるプロパティ データは、そのインスタンスのコピー内のプロパティ データとは関係ありません (ただし、値のクラスがハンドルを含む場合があります)。入力引数として渡された値オブジェクトは関数によって変更できますが、この変更内容は、元のオブジェクトには影響を及ぼしません。
これら 2 種類のクラスの動作と使用方法の詳細については、ハンドル クラスと値クラスの比較を参照してください。
値オブジェクトの引き渡し. 値オブジェクトを関数に渡す場合、関数はその引数変数のローカル コピーを作成します。関数は、そのコピーのみを変更できます。元のオブジェクトを変更する場合、変更されたオブジェクトを返して元の変数名を割り当てます。たとえば、以下の値クラス SimpleClass
を考えます。
classdef SimpleClass properties Color end methods function obj = SimpleClass(c) if nargin > 0 obj.Color = c; end end end end
Color
プロパティに red
という値を割り当てて、以下のように SimpleClass
のインスタンスを作成します。
obj = SimpleClass('red');
そのオブジェクトを関数 g
に以下のように渡します。この関数は、Color
プロパティに blue
を割り当てます。
function y = g(x) x.Color = 'blue'; y = x; end
y = g(obj);
関数 g
は、入力オブジェクトのコピーを変更し、そのコピーを返しますが、元のオブジェクトは変更しません。
y.Color
ans = blue
obj.Color
ans = red
関数 g
が値を返さなかった場合は、オブジェクトの Color
プロパティの変更は、関数ワークスペース内の obj
のコピーでのみ発生します。このコピーは、関数の実行が終了すると、スコープ外になります。
元の変数を上書きすると、その変数は、以下のように実際に新しいオブジェクトで置換されます。
obj = g(obj);
ハンドル オブジェクトの引き渡し. ハンドルを関数に渡すと、値オブジェクトを渡す場合とまったく同様に、その関数はハンドル変数のコピーを作成します。ただし、ハンドル オブジェクトのコピーは、元のハンドルと同じオブジェクトを参照するため、この関数は、変更したオブジェクトを返さずにオブジェクトを変更できます。
たとえば、SimpleClass
のクラス定義を変更して、handle
クラスから派生するクラスを作成するとします。
classdef SimpleHandleClass < handle properties Color end methods function obj = SimpleHandleClass(c) if nargin > 0 obj.Color = c; end end end end
Color
プロパティに red
という値を割り当てて、以下のように SimpleHandleClass
のインスタンスを作成します。
obj = SimpleHandleClass('red');
そのオブジェクトを関数 g
に以下のように渡します。この関数は、Color
プロパティに blue
を割り当てます。
y = g(obj);
関数 g
は、返されたハンドルと元のハンドルの両方のハンドルによって参照されるオブジェクトの Color
プロパティを以下のように設定します。
y.Color
ans = blue
obj.Color
ans = blue
変数 y
および変数 obj
は、以下のように同じオブジェクトを参照します。
y.Color = 'yellow';
obj.Color
ans = yellow
関数 g
は、入力引数 (obj
) によって参照されるオブジェクトを変更し、そのオブジェクトのハンドルを y
に出力しました。
MATLAB による値でのハンドルの引き渡し. ハンドル変数は、オブジェクトへの参照です。MATLAB では、この参照を値によって渡します。
ハンドルは、C++ での参照のようには動作しません。オブジェクト ハンドルを関数に渡し、この関数がハンドルの変数に異なるオブジェクトを割り当てた場合は、呼び出し元の関数にある変数は影響を受けません。たとえば、関数 g2
を以下のように定義したとします。
function y = g2(x) x = SimpleHandleClass('green'); y = x; end
ハンドル オブジェクトを関数 g2
に渡します。
obj = SimpleHandleClass('red');
y = g2(obj);
y.Color
ans = green
obj.Color
ans = red
関数は、引数として渡されたハンドルを上書きしますが、ハンドルによって参照されるオブジェクトは上書きしません。元のハンドル obj
は、以下のように、引き続き元のオブジェクトを参照します。
静的プロパティ
MATLAB では、クラスは定数プロパティを定義することはできますが、C++ のような他の言語で言う意味での "静的" プロパティは定義できません。定数プロパティは、クラス定義で指定された初期値から変更できません。
MATLAB には、変数は関数およびクラスの名前より常に優先されるという長年の規則があります。代入ステートメントは、変数が存在しない場合、それを導入します。
次の形式の式
A.B = C
は、値が C
のフィールド B
を含む struct
である、変数 A
を導入します。A.B = C
がクラス A
の静的プロパティを参照すると、クラス A
が変数 A
より優先されることになります。
この動作は、以前のリリースの MATLAB との著しい不整合をもたらします。たとえば、MATLAB パス上に A
という名前のクラスを配置すると、.m
コード ファイル内の A.B = C
のような代入ステートメントの意味が変わることになります。
他の言語では、クラス内のプライベート データとして、またはパブリック定数として以外、クラスは静的データをほとんど使用しません。MATLAB では、Java の public
final
static
フィールドを使用するのと同じ方法で定数プロパティを使用できます。MATLAB で、クラスの内部的なデータを使用するには、プライベートまたは保護されたメソッド内で永続変数を作成するか、クラスでプライベートに使用されるローカル関数を作成します。
MATLAB 内では静的データは避けてください。クラスに静的データがある場合、同じクラスを複数のアプリケーションで使用するとアプリケーション間で競合が発生します。競合は、他の言語ではそれほど問題ではありません。それらの言語では、異なるプロセスで実行する実行可能ファイルとしてアプリケーションをコンパイルします。各プロセスはそれ自身がクラスの静的データのコピーをもちます。MATLAB では、同じプロセスと環境内で各クラスの単一コピーを使用して多くの異なるアプリケーションを頻繁に実行します。
MATLAB で静的データを定義して使用する方法については、静的データを参照してください。
一般的なオブジェクト指向の手法
次の表には、他のオブジェクト指向言語で一般的に使用されるオブジェクト指向の手法について説明した節へのリンクが示されています。
手法 | MATLAB での使用方法 |
---|---|
演算子のオーバーロード | 演算子のオーバーロード |
多重継承 | 複数のクラスからのサブクラスの作成 |
サブクラス化 | サブクラス コンストラクターの設計 |
デストラクター | ハンドル クラスのデストラクター |
データ メンバーのスコープ | プロパティの属性 |
名前空間 (クラスのスコープ) | Create Namespaces |
名前付き定数 | 定数値をもつクラス プロパティの定義および名前付きの値を参照してください。 |
列挙値 | 列挙クラスの定義 |
静的メソッド | 静的メソッド |
静的プロパティ | サポートなし。変数 可変静的データについては、静的データを参照してください。 |
コンストラクター | クラス コンストラクター メソッド |
コピー コンストラクター | 同等の機能は存在しません。 |
参照/参照クラス | ハンドル クラスと値クラスの比較 |
抽象クラス/インターフェイス | 抽象クラスとクラス メンバー |
ガーベジ コレクション | オブジェクトのライフサイクル |
インスタンスのプロパティ | 動的プロパティ — インスタンスへのプロパティの追加 |
クラスのインポート | 関数への名前空間メンバーのインポート |
イベントとリスナー | イベントとリスナーの概念 |