Main Content

クラス メンバーのアクセス

基礎知識

この節では、以下の概念を理解していることを前提に説明を進めます。

 用語と概念

 クラス メンバーにアクセスするための値

アクセス制御リストの利用

特定のクラスのプロパティ、メソッドおよびイベントへのアクセスは、アクセス制御リストにより制御できます。アクセス制御リストでは、リストで指定されているクラスについて、そのクラス メンバーへのアクセスを許可できます。

この手法は、クラス システムの設計に、より高い自由度と制御を提供します。たとえば、複数のアクセス制御リストでクラスを別々に定義し、クラス システム外部からのクラス メンバーへのアクセスは許可しない、などです。

クラス メンバーへのアクセスの指定

メンバー アクセス属性ステートメントで特定のクラス メンバーにアクセスできるクラスを指定します。以下に例を示します。

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 配列

  • publicprotected または 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

AcListNonSubm1 のアクセス リスト内にあるため、そのメソッドは、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

アクセスなしのサブクラス

定義クラスをメソッドへのアクセス リストに含めると、そのクラスから派生するすべてのサブクラスにアクセスを与えることになります。定義ファイルを "持たない" アクセス リスト付きのメソッドをもつクラスから派生させる場合、以下のようになります。

  • サブクラス メソッドは、スーパークラス メソッドを呼び出すことができない。

  • サブクラス メソッドは、アクセス リスト内にあるクラスのインスタンスを使用して、スーパークラス メソッドを間接的に呼び出すことができる。

  • サブクラスは、スーパークラス メソッドをオーバーライドできない。

  • スーパークラス メソッドのアクセス リストにあるクラスのメソッドは非サブクラスだが、スーパークラス メソッドを呼び出せる。

たとえば、AcListSubAcListSuper のサブクラスです。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 として宣言されたメソッドを含んだクラスは、抽象クラスです。サブクラスは、クラス定義で宣言された関数シグネチャを使って抽象メソッドを実装しなければなりません。

抽象メソッドにアクセス リストがある場合、リスト内のクラスのみがメソッドを実装できます。アクセス リスト内にないサブクラスは抽象メソッドを実装できないので、サブクラス自身が抽象になります。

関連するトピック