クラス メンバーのアクセス
基礎知識
この節では、以下の概念を理解していることを前提に説明を進めます。
アクセス制御リストの利用
特定のクラスのプロパティ、メソッドおよびイベントへのアクセスは、アクセス制御リストにより制御できます。アクセス制御リストでは、リストで指定されているクラスについて、そのクラス メンバーへのアクセスを許可できます。
この手法は、クラス システムの設計に、より高い自由度と制御を提供します。たとえば、複数のアクセス制御リストでクラスを別々に定義し、クラス システム外部からのクラス メンバーへのアクセスは許可しない、などです。
クラス メンバーへのアクセスの指定
メンバー アクセス属性ステートメントで特定のクラス メンバーにアクセスできるクラスを指定します。以下に例を示します。
methods (Access = {?ClassName1,?ClassName2,...})
クラス matlab.metadata.Class
オブジェクトを使って、アクセス リストのクラスを参照します。複数のクラスを指定するには、matlab.metadata.Class
オブジェクトの cell 配列を使用します。名前空間内にあるクラスを参照する場合は、名前空間名を使用します。
メモ
matlab.metadata.Class
オブジェクトは明示的に指定し、?
演算子で作成します。関数またはその他の MATLAB 式で返された値では指定しません。
MATLAB の属性値の解釈方法
クラスのリストにアクセスを与えると、アクセスが次に対してのみ制限されます。
定義クラス
リスト内のクラス
リスト内のクラスのサブクラス
アクセス リストに定義クラスを含めると、定義クラスのすべてのサブクラスにアクセスを許可することになります。
MATLAB は、クラスが読み込まれるときにのみ、アクセス リストのクラスへの参照を解決します。MATLAB がアクセス リストに含まれているクラスを検出できない場合、そのクラスはアクセスから事実上削除されます。
MATLAB はリスト内の未解決の
matlab.metadata.Class
エントリを空のmatlab.metadata.Class
オブジェクトで置き換えます。空のアクセス リスト (つまり、空の cell 配列) は、
private
アクセスと同等です。
メタクラス オブジェクトの指定
?
演算子とクラス名のみを使用して matlab.metadata.Class
オブジェクトを生成します。属性に代入される値は、許可された属性値を返す関数も含め、他の MATLAB 式を含むことはできません。
matlab.metadata.Class
オブジェクトmatlab.metadata.Class
オブジェクトの cell 配列値
public
、protected
またはprivate
この節のコード例で説明されているように、これらの値を明示的に指定します。
アクセス リストをもつプロパティ
次のサンプル クラスでは、読み取りアクセス (GetAccess
) をクラスに与えるプロパティの動作を説明します。GrantAccess
クラスは、 Prop1
プロパティに NeedAccess
クラスへの GetAccess
を与えます。
classdef GrantAccess properties (GetAccess = ?NeedAccess) Prop1 = 7 end end
NeedAccess
クラスは、GrantAccess
Prop1
値の値を使用するメソッドを定義します。dispObj
メソッドは、Static
メソッドとして定義されますが、通常のメソッドとしても使用できます。
classdef NeedAccess methods (Static) function dispObj(GrantAccessObj) disp(['Prop1 is: ',num2str(GrantAccessObj.Prop1)]) end end end
Prop1
への get アクセスはプライベートのため、クラス定義の外部からプロパティへのアクセスを試みると、MATLAB はエラーを返します。たとえば、コマンド ラインから次のように実行します。
a = GrantAccess; a.Prop1
Getting the 'Prop1' property of the 'GrantAccess' class is not allowed.
ただし、MATLAB は、NeedAccess
クラスによる Prop1
へのアクセスを許可します。
NeedAccess.dispObj(a)
Prop1 is: 7
アクセス リストをもつメソッド
メソッドへのアクセスを与えられたクラスは、次のことができます。
定義クラスのインスタンスを使ってメソッドを呼び出す。
同じ名前で自身のメソッドを定義する (サブクラスでない場合)。
メソッドを定義しているスーパークラスにそれ自身またはアクセス リストにサブクラスが含まれている場合にのみ、サブクラスのメソッドをオーバーライドする。
次のサンプル クラスでは、アクセス リストにある他のクラスのメソッドから呼び出されたメソッドの動作について説明します。クラス AcListSuper
は、m1
メソッドに AcListNonSub
クラス アクセスを与えます。
classdef AcListSuper methods (Access = {?AcListNonSub}) function obj = m1(obj) disp ('Method m1 called') end end end
AcListNonSub
は m1
のアクセス リスト内にあるため、そのメソッドは、AcListSuper
のインスタンスを使って m1
を呼び出せます。
classdef AcListNonSub methods function obj = nonSub1(obj,AcListSuper_Obj) % Call m1 on AcListSuper class AcListSuper_Obj.m1; end function obj = m1(obj) % Define a method named m1 disp(['Method m1 defined by ',class(obj)]) end end end
両方のクラスのオブジェクトを作成します。
a = AcListSuper; b = AcListNonSub;
AcListNonSub
メソッドを使って AcListSuper
m1
メソッドを呼び出します。
b.nonSub1(a);
Method m1 called
AcListNonSub
m1
メソッドを呼び出します。
b.m1;
Method m1 defined by AcListNonSub
アクセスなしのサブクラス
定義クラスをメソッドへのアクセス リストに含めると、そのクラスから派生するすべてのサブクラスにアクセスを与えることになります。定義ファイルを "持たない" アクセス リスト付きのメソッドをもつクラスから派生させる場合、以下のようになります。
サブクラス メソッドは、スーパークラス メソッドを呼び出すことができない。
サブクラス メソッドは、アクセス リスト内にあるクラスのインスタンスを使用して、スーパークラス メソッドを間接的に呼び出すことができる。
サブクラスは、スーパークラス メソッドをオーバーライドできない。
スーパークラス メソッドのアクセス リストにあるクラスのメソッドは非サブクラスだが、スーパークラス メソッドを呼び出せる。
たとえば、AcListSub
は AcListSuper
のサブクラスです。AcListSuper
クラスは、メソッド m1
のアクセス リストを定義します。ただし、このリストには AcListSuper
が含まれていないため、AcListSuper
のサブクラスはメソッド m1
にアクセスできません。
classdef AcListSub < AcListSuper methods function obj = sub1(obj,AcListSuper_Obj) % Access m1 via superclass object (***NOT ALLOWED***) AcListSuper_Obj.m1; end function obj = sub2(obj,AcListNonSub_Obj,AcListSuper_obj) % Access m1 via object that is in access list (is allowed) AcListNonSub_Obj.nonSub1(AcListSuper_Obj); end end end
スーパークラス メソッドを直接呼び出すことはできない
サブクラスは m1
のアクセス リストに含まれていないため、sub1
メソッドからスーパークラス m1
メソッドを呼び出そうとすると、エラーが発生します。
a = AcListSuper; c = AcListSub; c.sub1(a);
Cannot access method 'm1' in class 'AcListSuper'. Error in AcListSub/sub1 (line 4) AcListSuper_Obj.m1;
スーパークラス メソッドを間接的に呼び出す
スーパークラス メソッドのアクセス リストに含まれているクラスのオブジェクトを使用して、スーパークラス メソッドにアクセスできないサブクラスからそのメソッドを呼び出すことができます。
AcListSub
sub2
メソッドは m1
のアクセス リストに含まれているクラス (AcListNonSub
) のメソッドを呼び出します。このメソッド nonSub1
はスーパークラス m1
メソッドにアクセスできます。
a = AcListSuper; b = AcListNonSub; c = AcListSub; c.sub2(b,a);
Method m1 called
スーパークラス メソッドは再定義できない
サブクラスがメソッドのアクセス リストに含まれていない場合、サブクラスは同じ名前でメソッドを定義できません。この動作は、メソッド Access
が明示的に private
として宣言されている場合の動作とは異なります。
たとえば、次のメソッドを AcListSub
クラス定義に追加すると、クラスをインスタンス化しようとするときにエラーが発生します。
methods (Access = {?AcListNonSub}) function obj = m1(obj) disp('AcListSub m1 method') end end
c = AcListSub;
Class 'AcListSub' is not allowed to override the method 'm1' because neither it nor its superclasses have been granted access to the method by class 'AcListSuper'.
スーパークラスをリスト内のクラスからサブクラス経由で呼び出す
AcListNonSub
クラスは m1
メソッドのアクセス リストに含まれています。このクラスは、AcListSub
クラスのオブジェクトを使用して m1
メソッドを呼び出すメソッドを定義できます。AcListSub
はメソッド m1
のアクセス リスト内にはありませんが、AcListSuper
のサブクラスです。
たとえば、次のメソッドを AcListNonSub
クラスに追加します。
methods function obj = nonSub2(obj,AcListSub_Obj) disp('Call m1 via subclass object:') AcListSub_Obj.m1; end end
nonSub2
メソッドを呼び出すと、スーパークラス m1
メソッドが実行されます。
b = AcListNonSub; c = AcListSub; b.nonSub2(c);
Call m1 via subclass object: Method m1 called
この動作は、任意のサブクラス オブジェクトの動作で一貫しており、そのスーパークラスのオブジェクトの代用とすることができます。
アクセス リストをもつ抽象メソッド
Abstract
として宣言されたメソッドを含んだクラスは、抽象クラスです。サブクラスは、クラス定義で宣言された関数シグネチャを使って抽象メソッドを実装しなければなりません。
抽象メソッドにアクセス リストがある場合、リスト内のクラスのみがメソッドを実装できます。アクセス リスト内にないサブクラスは抽象メソッドを実装できないので、サブクラス自身が抽象になります。