How to obtain static member variables in MATLAB classes?

后端 未结 4 1638
名媛妹妹
名媛妹妹 2020-12-03 03:36

Is there a way to define static member variables in MATLAB classes?

This doesn\'t work:

classdef A

    properties ( Static )
        m = 0;
    end
         


        
相关标签:
4条回答
  • 2020-12-03 04:10

    Here's a direct way to create a static property in Matlab. The only difference between this implementation and a hypothetical (but impossible; see Mikhail's answer) true static property is the syntax for setting the member variable.

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

    Now the static property staticVar can be read via:

    StaticVarClass.staticVar
    

    ...and be set via:

    StaticVarClass.staticVar(newval);
    

    So, for instance, this is the expected output from a test of this functionality:

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

    This approach works just as well for private static properties like you requested, but the demo code is a little longer. Note that this is not a handle class (though it would work perfectly well on a handle class as well).

    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
    

    ...and the test:

    >> x = StaticVarClass
      x = 
          StaticVarClass with no properties.
          Methods
    >> x.getStatic
      ans =
          []
    >> x.setStatic('foobar')
      ans = 
          StaticVarClass with no properties.
          Methods
    >> x.getStatic
      ans =
          foobar
    >> 
    
    0 讨论(0)
  • 2020-12-03 04:12

    You can not, it is by design. You should use a persistent variable (technique from the MATLAB as 1980 applied in year 2011)!

    For completeness I should mention that actually there is as of 2010b an undocumented and probably not longer supported static property modifier.

    For background see here the answer of Dave Foti, MATLAB OO group manager:

    In MATLAB, classes can define Constant properties, but not "static" properties in the sense of other languages like C++. There were beta releases that experimented with "Static" properties and the undocumented attribute remains from then. However, the Static attribute is undocumented, should not be used, and will likely be removed in a future MATLAB release. R2008a implements it as a synonym for Constant and provides no additional functionality beyond the documented behavior of Constant properties.

    Constant properties may not be changed from the initial value specified in the property declaration. There are a couple of reasons why MATLAB works the way it does. First, MATLAB has longstanding rules that variables always take precedent over the names of functions and classes and that assignment statements introduce a variable if one doesn't already exist. Thus, any expression of the form "A.B = C" will introduce a new variable A that is a struct array containing a field B whose value is C. If "A.B = C" could refer to a static property of class A, then class A would take precedent over variable A and this would be a very significant incompatibility with prior releases of MATLAB. It would mean that an m-file containing the assignment statement "A.B = C" could have its meaning changed by the introduction of a class named A somewhere on the MATLAB path. MATLAB programmers have always been able to rely on assignment statements introducing variables that shadow any other use of the same name.

    Second, we have observed that static data is rarely used in other classes except as private data within the class or as public constants. For example, a survey of several Java class libraries found that all public static fields were also final. In MATLAB, Constant properties can be used like "public final static" fields in Java. For data internal to a class, MATLAB already has persistent variables that can be created inside of private or protected methods or local functions privately used by a class. There are also good reasons to avoid static data in MATLAB where possible. If a class has static data, it can be difficult to use the same class in multiple applications because the static data can be a source of conflicts among applications. In some other languages, this is less of an issue because different applications are separately compiled into executables running in different processes with different copies of class static data. In MATLAB, frequently many different applications may be running in the same process and environment with a single copy of each class.

    0 讨论(0)
  • 2020-12-03 04:21

    Another workaround to get something like static properties is to use the fact that initialisation code for member variables is only executed once when the class file is loaded. That means, if you have a definition like

    classdef foo
        properties
            stuff = some_function()
        end
    end
    

    then some_function is invoked only once, and if it returns an object of class type, this will be shared by all instances. I've added a sample implementation that shows how that can be used:

    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
    

    If you run this sample code

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

    you'll see, that classvars is indeed shared. I think this solution is much nicer than using persistent variables in functions, since you can reuse the StaticVarContainer as often as you want, it's easier to use, and furthermore, you directly see the initialisation of the static variables in the properties section.

    To get the result, that is desired in the OP's question (i.e. implementing an object counter) the shared property can be made Constant, so that it can be referenced without an instance at hand:

    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
    

    Note, that the Constant attribute only means that, e.g. obj1.static cannot be changed, but it does not affect obj1.static.counter which is not constant, and can be set to heart's desire.

    0 讨论(0)
  • 2020-12-03 04:25

    (just to inform) there is (another?) way to create static-like data in matlab

    suppose that you have a "handle" class which its name is "car" if you want the car class to have static data, you could construct another handle class and use it in car class throw composition, the latter class works as a static data for car class

    classdef car<handle 
        properties 
             static_data:STATIC_DATA_HOLDER;
        end
    end
    
    classdef STATIC_DATA_HOLDER<handle
        properties
            data
        end
    end
    

    this way when you create first instance of a car class, an instance of STATIC_DATA_HOLDER will be created and when you create second instance of car class it uses previously created STATIC_DATA_HOLDER class.

    these code tested with "MATLAB 2013b"

    0 讨论(0)
提交回复
热议问题