【问题标题】:How to obtain static member variables in MATLAB classes?MATLAB类中如何获取静态成员变量?
【发布时间】:2011-09-20 23:14:08
【问题描述】:

有没有办法在 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

【问题讨论】:

  • AFAIK 不适合它,但 persistent 有效吗?
  • 是的,我在静态成员函数中获得了使用持久变量的解决方法。
  • 您应该将其发布为其他对此问题感兴趣的人的答案
  • persistent 虽然不会为子类单独分配

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


【解决方案1】:

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

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

背景见hereDave Foti的答案,MATLAB OO组经理:

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

常量属性不可更改 从指定的初始值 财产声明。有一个 MATLAB 工作的几个原因 它的方式。首先,MATLAB有 变量的长期规则 总是优先于名字 函数和类以及 赋值语句引入了一个 变量,如果一个尚不存在。 因此,任何形式为“A.B = C" 将引入一个新变量 A,它是一个包含 a 值为 C 的字段 B。如果“A.B = C” 可以引用的静态属性 A类,然后A类将采取 变量 A 和 this 的先例 将是一个非常重要的 与先前版本不兼容 的MATLAB。这将意味着一个 包含分配的 m 文件 声明“A.B = C”可以有它的 被介绍改变的意思 某处名为 A 的类 MATLAB 路径。 MATLAB 程序员有 总是能够依靠分配 引入变量的语句 隐藏同名的任何其他使用。

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

【讨论】:

  • 遗憾的是“这里”链接已损坏:(
【解决方案2】:

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

【讨论】:

    【解决方案3】:

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

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

    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”测试

    【讨论】:

    【解决方案4】:

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

    的定义
    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不固定,可随心所欲设置。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多