15

MATLAB クラスで静的メンバー変数を定義する方法はありますか?

これは機能しません:

classdef A

    properties ( Static )
        m = 0;
    end
end

「Static」の代わりに「Constant」というキーワードを使用することをお勧めします。定数のプロパティは変更できません。class のすべてのオブジェクトに共通の変数がA必要で、その変数を class のメソッドで変更できるようにしたいと考えていますA

したがって、私が必要とするのはプライベート静的メンバー変数です。MATLAB で取得する方法はありますか?


静的メンバー関数で永続変数を使用して回避策を実行できることがわかりました。

この場合、次のような基本クラスからすべてのクラスを継承する必要があります。

classdef object < handle

    properties ( GetAccess = 'public', SetAccess = 'private' )
        id
    end

    methods ( Access = 'protected' )
        function obj = object()
            obj.id = object.increment();
        end
    end

    methods ( Static, Access = 'private' )
        function result = increment()
            persistent stamp;
            if isempty( stamp )
                stamp = 0;
            end
            stamp = stamp + uint32(1);
            result = stamp;
        end
    end  
end
4

4 に答える 4

16

できません。これは仕様です。変数を使用する必要がありpersistentます (1980 年に 2011 年に適用された MATLAB の手法)。

完全を期すために、実際には 2010b の時点で文書化されておらず、おそらくサポートされていないstaticプロパティ修飾子があることに言及する必要があります。

背景については、MATLAB OO グループ マネージャーであるDave Fotiの回答を参照してください。

MATLAB では、クラスは定数プロパティを定義できますが、C++ などの他の言語の意味での「静的」プロパティは定義できません。「静的」プロパティを試したベータ リリースがあり、文書化されていない属性はそれ以降残っています。ただし、静的属性は文書化されておらず、使用すべきではなく、将来の MATLAB リリースで削除される可能性があります。R2008a はこれを Constant のシノニムとして実装し、Constant プロパティの文書化された動作以外の追加機能を提供しません。

定数プロパティは、プロパティ宣言で指定された初期値から変更できません。MATLAB がこのように機能する理由はいくつかあります。まず、MATLAB には、関数やクラスの名前よりも常に変数が優先され、代入ステートメントで変数がまだ存在しない場合は変数が導入されるという長年の規則があります。したがって、「AB = C」という形式の式は、値が C であるフィールド B を含む構造体配列である新しい変数 A を導入します。「AB = C」がクラス A の静的プロパティを参照できる場合、クラスA は変数 A より優先され、これは MATLAB の以前のリリースとの非常に重大な非互換性になります。これは、割り当てステートメント「AB = C」を含む m-ファイルを意味します。MATLAB パスのどこかに A という名前のクラスを導入することで、その意味が変わる可能性があります。MATLAB プログラマーは、同じ名前の他の使用を隠す変数を導入する割り当てステートメントに常に依存することができました。

次に、静的データは、クラス内のプライベート データまたはパブリック定数として使用される場合を除いて、他のクラスではめったに使用されないことがわかりました。たとえば、いくつかの Java クラス ライブラリを調査したところ、すべての public static フィールドも final であることがわかりました。MATLAB では、定数プロパティは Java の "public final static" フィールドのように使用できます。クラス内部のデータの場合、MATLAB には既に、クラスによってプライベートに使用されるプライベート メソッドまたはプロテクト メソッドまたはローカル関数内で作成できる永続変数があります。可能であれば、MATLAB で静的データを避けるべき十分な理由もあります。クラスに静的データがある場合、複数のアプリケーションで同じクラスを使用するのが難しい場合があります。これは、静的データがアプリケーション間の競合の原因になる可能性があるためです。他のいくつかの言語では、さまざまなアプリケーションが、クラスの静的データのさまざまなコピーを使用してさまざまなプロセスで実行される実行可能ファイルに個別にコンパイルされるため、これはそれほど問題ではありません。MATLAB では、各クラスの 1 つのコピーを使用して、多くの異なるアプリケーションが同じプロセスおよび環境で実行されていることがよくあります。

于 2011-06-23T11:12:57.617 に答える
11

Matlab で静的プロパティを作成する直接的な方法を次に示します。この実装と架空の (しかし不可能です。Mikhail の回答を参照してください) 真の静的プロパティとの唯一の違いは、メンバー変数を設定するための構文です。

classdef StaticVarClass
    methods (Static = true)
        function val = staticVar(newval)
            persistent currentval;
            if nargin >= 1
                currentval = newval;
            end
            val = currentval;
        end
    end
end

これで、静的プロパティ staticVar を次の方法で読み取ることができます。

StaticVarClass.staticVar

...そして次の方法で設定します:

StaticVarClass.staticVar(newval);

したがって、たとえば、これはこの機能のテストから予想される出力です。

>> StaticVarClass.staticVar
  ans =
      []
>> StaticVarClass.staticVar('foobar')
  ans =
      foobar
>> StaticVarClass.staticVar
  ans =
      foobar
>> 

このアプローチは、要求されたようなプライベートな静的プロパティでも同様に機能しますが、デモ コードは少し長くなります。これはハンドル クラスではないことに注意してください (ただし、ハンドル クラスでも完全に機能します)。

classdef StaticVarClass
    methods (Access = private, Static = true)
        function val = staticVar(newval)
            persistent currentval;
            if nargin >= 1
                currentval = newval;
            end
            val = currentval;
        end
    end

    methods
        function this = setStatic(this, newval)
            StaticVarClass.staticVar(newval);
        end

        function v = getStatic(this)
            v = StaticVarClass.staticVar;
        end
    end
end

...そしてテスト:

>> x = StaticVarClass
  x = 
      StaticVarClass with no properties.
      Methods
>> x.getStatic
  ans =
      []
>> x.setStatic('foobar')
  ans = 
      StaticVarClass with no properties.
      Methods
>> x.getStatic
  ans =
      foobar
>> 
于 2013-01-28T21:07:16.323 に答える
0

静的プロパティのようなものを取得する別の回避策は、メンバー変数の初期化コードがクラス ファイルのロード時に 1 回だけ実行されるという事実を利用することです。つまり、次のような定義がある場合

classdef foo
    properties
        stuff = some_function()
    end
end

thensome_functionは一度だけ呼び出され、クラス型のオブジェクトを返す場合、これはすべてのインスタンスで共有されます。その使用方法を示すサンプル実装を追加しました。

classdef ClassWithStaticMembers
    properties
        classvars = StaticVarContainer('foo', 0, 'bar', 2);
        othervar
    end
    methods
        function obj=ClassWithStaticMembers(var)
            obj.othervar = var;
        end
    end 
end

classdef StaticVarContainer < dynamicprops
    methods
        function obj=StaticVarContainer(varargin)
            for i=1:2:numel(varargin)
                obj.addprop(varargin{i});
                obj.(varargin{i}) = varargin{i+1};
            end
        end
    end
end

このサンプルコードを実行すると

obj1 = ClassWithStaticMembers(3);
obj2 = ClassWithStaticMembers(5);
obj1.classvars.foo = [2,3];

obj1.othervar
obj1.classvars

obj2.othervar
obj2.classvars

ご覧のとおり、それclassvarsは実際に共有されています。このソリューションは、関数で永続変数を使用するよりもはるかに優れていると思います。好きなだけ再利用でき、StaticVarContainer使いやすく、さらに、プロパティセクションで静的変数の初期化を直接確認できるからです。

結果を取得するには、OP の質問 (つまり、オブジェクト カウンターの実装) で必要な共有プロパティを作成Constantして、手元にインスタンスがなくても参照できるようにします。

classdef ClassWithCounter
    properties (Constant)
        static = StaticVarContainer('counter', 0);
    end
    methods
        function obj=ClassWithCounter()
            obj.static.counter = obj.static.counter + 1;
        end
    end 
end

clear all
obj1 = ClassWithCounter();
obj2 = ClassWithCounter();
obj3 = ClassWithCounter();

ClassWithCounter.static.counter

Constant属性は、たとえばobj1.static変更できないことを意味するだけobj1.static.counterであり、一定でないものには影響せず、思いのままに設定できることに注意してください。

于 2015-11-25T16:49:20.563 に答える