如何在MATLAB类中获取静态成员变量?

时间:2011-06-23 06:37:10

标签: matlab class oop static-functions matlab-class

有没有办法在MATLAB类中定义静态成员变量?

这不起作用:

classdef A

    properties ( Static )
        m = 0;
    end
end

建议使用关键字“常量”而不是“静态”,不能修改常量属性。我想要一个类A的所有对象共有的变量,我希望能够在类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 个答案:

答案 0 :(得分:15)

你不能,这是设计的。您应该使用persistent变量(2011年应用于1980年的MATLAB技术)!

为了完整性,我应该提一下,实际上2010b是一个未记录的,可能不再受支持的static属性修饰符。

有关背景,请参阅here MATLAB OO小组经理Dave Foti的答案:

  

在MATLAB中,类可以定义Constant   属性,但不是“静态”   在其他意义上的属性   像C ++这样的语言。有测试版   试验的版本   “静态”属性和   未记录的属性仍然来自   然后。但是,Static属性是   没有证件,不应该使用,和   很可能在将来被删除   MATLAB发布。 R2008a实现了它   作为Constant的同义词并提供   没有额外的功能   Constant的记录行为   属性。

     

不能更改常量属性   从中指定的初始值   财产申报。有一个   MATLAB工作的几个原因   它的方式。首先,MATLAB有   长期存在的变量规则   总是先于名字   功能和类和那些   赋值语句介绍一个   变量,如果还不存在。   因此,任何形式的表达“A.B   = C“将引入一个新变量A,它是一个包含a的结构数组   字段B,其值为C.如果“A.B = C”   可以引用的静态属性   A级,然后是A级   变量A的先例和这个   会非常重要   与先前版本不兼容   MATLAB。这意味着一个   包含作业的m文件   声明“A.B = C”可以有它的   引言改变了意义   一个名为A的类在某个地方   MATLAB路径。 MATLAB程序员有   总是能够依靠任务   引入变量的语句   影响任何其他相同名称的使用。

     

其次,我们观察到静电   数据很少在其他类中使用   除了作为私人数据   类或公共常量。对于   例如,几个Java的调查   班级图书馆发现全部公开   静态领域也是最终的。在   MATLAB,常量属性即可   用过“public final static”   Java中的字段。对于内部数据   类,MATLAB已经具有持久性   可以在里面创建的变量   私人或受保护的方法或   一个私人使用的本地函数   类。还有很好的理由   避免在MATLAB中的静态数据   可能。如果一个类有静态数据,   它可能很难使用相同的   多个应用程序中的类   因为静态数据可以是一个   的冲突根源   应用。在其他一些语言中,   这不是一个问题,因为   不同的应用是分开的   编译成运行的可执行文件   不同的流程有所不同   类静态数据的副本。在   MATLAB,经常有很多不同   应用程序可能正在运行   同样的过程和环境   每个班级的单一副本。

答案 1 :(得分: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
>> 

答案 2 :(得分:1)

(只是告知) 有(另一种?)方法在matlab中创建类似静态的数据

假设你有一个&#34;句柄&#34;它的名字是&#34; car&#34; 如果你想要汽车类有静态数据,你可以构建另一个句柄类并在汽车类投掷组合中使用它,后一个类作为汽车类的静态数据

classdef car<handle 
    properties 
         static_data:STATIC_DATA_HOLDER;
    end
end

classdef STATIC_DATA_HOLDER<handle
    properties
        data
    end
end

这样,当您创建汽车类的第一个实例时,将创建一个STATIC_DATA_HOLDER实例,当您创建汽车类的第二个实例时,它会使用以前创建的STATIC_DATA_HOLDER类。

这些代码用&#34; MATLAB 2013b&#34;

答案 3 :(得分:0)

获得类似静态属性的另一种解决方法是使用成员变量的初始化代码仅在加载类文件时执行一次的事实。这意味着,如果您有像

这样的定义
classdef foo
    properties
        stuff = some_function()
    end
end

然后只调用some_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,这不是常量,可以设置为内心的愿望。