Main Content

プロパティ初期化の順序依存を回避

プロパティ読み込みの制御

load がプロパティ値を設定する順序にプロパティ値が依存している場合、問題が生じることがあります。

クラスの設計が次の両方に該当するとします。

  • プロパティの set メソッドが別のプロパティ値を変更する。

  • プロパティ値が他のプロパティ値から算出される。

この場合、一連のプロパティ値を変更した後のオブジェクトの最終的な状態は、プロパティを設定する順序に左右される可能性があります。この順序への依存関係は、オブジェクトの読み込み結果に影響を及ぼす可能性があります。

関数 load はプロパティ値を特定の順序で設定します。この順序は、保存されたオブジェクトのプロパティが設定された順序とは異なる場合があります。結果として、読み込まれたオブジェクトには、保存したときとは異なるプロパティ値が設定される可能性があります。

非依存プロパティの復元

プロパティの関数 set が他のプロパティの値を変更する場合は、そのプロパティの Dependent 属性を true に設定します。MATLAB® は依存プロパティの値の保存または復元をしません。

依存プロパティによって設定された値を保存するには、非依存プロパティを使用します。この場合、関数 load は保存されたものと同じ値で非依存プロパティを復元します。関数 load は依存プロパティの set メソッドを呼び出しません。保存されたファイルにそのプロパティの値が存在しないためです。

プライベート ストレージをもつ依存プロパティ

Odometer クラスは、オブジェクト読み込みの際に、復元するプロパティを制御することによって順序への依存を回避します。

  • Units プロパティは依存関係にあります。このプロパティの set メソッドは TotalDistance プロパティを設定します。したがって、loadUnits プロパティの set メソッドを呼び出しません。

  • 関数 load は、TotalDistance をオブジェクト保存時の値に復元します。

classdef Odometer
   properties(Constant)
      ConversionFactor = 1.6
   end
   properties
      TotalDistance = 0
   end
   properties(Dependent)
      Units
   end
   properties(Access=private)
      PrivateUnits = 'mi'
   end
   methods
      function unit = get.Units(obj)
         unit = obj.PrivateUnits;
      end
      function obj = set.Units(obj,newUnits)
         % validate newUnits to be a char vector
         switch(newUnits)
            case 'mi'
               if strcmp(obj.PrivateUnits,'km')
                  obj.TotalDistance = obj.TotalDistance / ...
                     obj.ConversionFactor;
                  obj.PrivateUnits = newUnits;
               end
            case 'km'
               if strcmp(obj.PrivateUnits,'mi')
                  obj.TotalDistance = obj.TotalDistance * ...
                     obj.ConversionFactor;
                  obj.PrivateUnits = newUnits;
               end
            otherwise
               error('Odometer:InvalidUnits', ...
                  'Units ''%s'' is not supported.', newUnits);
         end
      end
   end
end

Odometer のインスタンスを作成し、次のプロパティ値を設定するとします。

odObj = Odometer;
odObj.Units = 'km';
odObj.TotalDistance = 16;

オブジェクトを保存する際は、次のようになります。

  • ConversionFactor は、Constant プロパティなので保存されません。

  • TotalDistance は保存されます。

  • UnitsDependent プロパティなので保存されません。

  • PrivateUnits は保存され、Units の現在値に対してストレージを与えます。

オブジェクトを読み込む際は、次のようになります。

  • ConversionFactor はクラス定義から得られます。

  • TotalDistance は読み込まれます。

  • Units は読み込まれないので、その set メソッドは呼び出されません。

  • PrivateUnits は保存されたオブジェクトから読み込まれます。

Units プロパティが Dependent でない場合、読み込むと、その set メソッドを呼び出し、TotalDistance プロパティが再び設定されます。

他のプロパティから計算されたプロパティ値

Odometer2 クラスの TripDistance プロパティは、他の 2 つのプロパティ TotalDistance および TripMarker のみに依存しています。

このクラスでは、読み込み時にプロパティ値を初期化する際、TripDistance プロパティを dependent にすることで順序への依存を回避します。MATLAB は TripDistance プロパティの値の保存や読み込みを行いませんが、プロパティ get メソッドで TripDistance の計算に使用する 2 つのプロパティの値は保存して読み込みます。

classdef Odometer2
   properties
      TotalDistance = 0
      TripMarker = 0
   end
   properties(Dependent)
      TripDistance
   end
   methods
      function distance = get.TripDistance(obj)
         distance = obj.TotalDistance - obj.TripMarker;
      end
   end
end

関連するトピック