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

发布于 2024-11-16 22:02:25 字数 939 浏览 1 评论 0原文

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

这不起作用:

classdef A

    properties ( Static )
        m = 0;
    end
end

建议使用关键字“Constant”而不是“Static”,常量属性无法修改。我想要一个对于类 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

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

This doesn't work:

classdef A

    properties ( Static )
        m = 0;
    end
end

It suggests to use keyword "Constant" instead of "Static", the constant properties cannot be modified. I want a variable common to all objects of class A and I want to be able to modify that variable in methods of class A.

So what I need is a private static member variable. Is there a way to obtain it in MATLAB?


Found out that a workaround can be done using persistent variables in static member functions.

In this case you should inherit all your classes from a base class like the following.

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

留蓝 2024-11-23 22:02:25

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

为了完整起见,我应该提到,实际上从 2010b 开始,就有一个未记录且可能不再受支持的 static 属性修饰符。

有关背景信息,请参阅此处答案Dave Foti,MATLAB OO 小组经理:

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

常量属性不能改变
从指定的初始值
财产申报。有一个
MATLAB 工作的几个原因
就是这样。首先,MATLAB 有
变量的长期规则
始终优先于名称
函数和类的组成
赋值语句引入了
变量(如果尚不存在)。
因此,任何“AB”形式的表达式
= C”将引入一个新变量 A,它是一个包含
字段 B 的值为 C。如果“AB = C”
可以引用静态属性
A 类,那么 A 类将采取
变量 A 和 this 的先例
将是一个非常有意义的
与先前版本不兼容
MATLAB 的。这意味着
包含作业的 m 文件
语句“AB = C”可能有其
含义因介绍而改变
某处名为 A 的类的
MATLAB 路径。 MATLAB 程序员有
总是能够依赖作业
引入变量的语句
屏蔽同名的任何其他使用。

其次,我们观察到静态
数据很少在其他类中使用
除非作为私有数据
类或作为公共常量。为了
例如,对几个 Java 的调查
类库发现所有公共
静态字段也是最终的。在
MATLAB,常量属性可以是
用法类似于“公共最终静态”
Java 中的字段。对于内部数据
类,MATLAB已经有持久化的
可以在里面创建变量
私有或受保护的方法或
私有的局部函数
班级。也有充分的理由
避免在 MATLAB 中使用静态数据,其中
可能的。如果一个类有静态数据,
使用相同的可能很困难
多个应用程序中的类
因为静态数据可以是
人与人之间矛盾的根源
应用程序。在其他一些语言中,
这不是什么问题,因为
不同的应用是分开的
编译成可执行文件运行
不同的流程有不同的
类静态数据的副本。在
MATLAB,通常有许多不同的
应用程序可能正在运行
相同的流程和环境
每个类都有一个副本。

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.

最笨的告白 2024-11-23 22:02:25

这是在 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
>> 

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
>> 
素食主义者 2024-11-23 22:02:25

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

假设您有一个“handle”类,其名称为“car”
如果您希望汽车类具有静态数据,您可以构造另一个句柄类并在汽车类抛出组合中使用它,后一个类作为汽车类的静态数据,

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 类。

这些代码使用“MATLAB 2013b”进行了测试

(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"

无语# 2024-11-23 22:02:25

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

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问题中所期望的结果(即实现对象计数器),可以将共享属性设置为常量,以便可以在手头没有实例的情况下引用它:

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,并且可以根据自己的意愿进行设置。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文