代码之家  ›  专栏  ›  技术社区  ›  divB

MATLAB中的属性初始化

  •  1
  • divB  · 技术社区  · 6 年前

    classdef A
        properties
           foo = 'bar';
        end
    end
    

    或者通过显式定义构造函数:

    classdef B
        properties
            foo;
        end
    
        methods this = B()
            this.foo = 'bar';
        end
    end
    

    哪种方法更可取?

    (我之所以问这个问题,是因为C++中有一个类似的例子,其中首选的方法是在构造函数之后用冒号初始化成员变量,而不是在构造函数中赋值)。

    2 回复  |  直到 6 年前
        1
  •  2
  •   Sam Roberts David Peden    6 年前

    在大多数情况下,这两种方法的行为是相同的,选择只是一种偏好,取决于您觉得哪个更清晰/更容易维护等等。

    本质区别在于,每次构造对象时,构造函数中初始化的属性都会单独初始化,而在属性块中使用默认值初始化的属性会在第一次读取类定义时初始化一次。属性块中的默认值是 ,而不是对象;并且(使用反射)可以查询该默认值,即使尚未实例化该类的任何实例。

    在大多数情况下,这没有什么区别——但是当初始值是句柄对象,或者是不确定函数的输出时,它就有区别了。因此,请考虑以下两类:

    classdef A
        properties
            foo
        end
        methods
            function obj = A
                obj.foo = containers.Map;
            end
        end
    end
    
    classdef B
        properties
            foo = containers.Map
        end
    end
    

    containers.Map 是句柄类。

    A A 容器。地图 foo . 在 B ,每个实例 B类 相同的 容器。地图 因为它 ,因为属性只初始化一次,所以是第一次读取类定义。所以如果你修改 对于任何类的对象 ,则该更改将传播到类的所有其他实例 ,如您所见:

    >> a1 = A; a2 = A; a1.foo('greeting') = 'hello'; a2.foo('greeting') = 'bonjour';
    >> a1.foo('greeting'), a2.foo('greeting')
    ans =
        'hello'
    ans =
        'bonjour'
    >> b1 = B; b2 = B; b1.foo('greeting') = 'hello'; b2.foo('greeting') = 'bonjour';
    >> b1.foo('greeting'), b2.foo('greeting')
    ans =
        'bonjour'
    ans =
        'bonjour'
    >> % Note that b1.foo has changed as a result of setting b2.foo
    

    关于将类作为默认值处理的这一点常常会让人感到困惑;但是这种行为并不特定于处理类。例如,考虑以下变化:

    classdef A
        properties
            foo
        end
        methods
            function obj = A
                obj.foo = datetime('now');
            end
        end
    end
    
    classdef B
        properties
            foo = datetime('now')
        end
    end
    

    在这里 将存储每个对象的创建时间,而 将为所有对象存储类首次初始化的时间,无论这些对象是何时创建的。

    https://undocumentedmatlab.com/blog/handle-object-as-default-class-property-value ,特别是那篇文章下面的评论线程,用于讨论这个问题,并解释以这种方式设计MATLAB的原因。


    clear 以及它与这个问题的关系。

    使用上述类的第二个实现(使用 datetime ),请看以下内容:

    >> a = A; b = B; datestr(a.foo), datestr(b.foo)
    ans =
        '01-Sep-2018 18:59:30'
    ans =
        '01-Sep-2018 18:59:30'
    >> clear variables
    >> a = A; b = B; datestr(a.foo), datestr(b.foo)
    ans =
        '01-Sep-2018 18:59:48'
    ans =
        '01-Sep-2018 18:59:30'
    >> clear classes
    >> a = A; b = B; datestr(a.foo), datestr(b.foo)
    ans =
        '01-Sep-2018 18:59:57'
    ans =
        '01-Sep-2018 18:59:57'
    

    所以我们首先创建一个 A B类 s、 它们同时出现。那我们等一会儿,好吗 clear variables A 是新的时间 B类 还是和以前一样。最后我们再等一段时间 clear classes A 有新的时间。

    为什么?因为 只是从工作区中删除对变量的引用。的类定义 B类 没有清除,所以当我们创建另一个 B类 ,它仍然使用第一次读取类定义时的值。 清除类 ,所以当我们以后构建一个新的 B类 A ,作为

    清除类 清除 全部的 B类 使用 clear B

        2
  •  0
  •   Community Mr_and_Mrs_D    4 年前

    这是你的选择,除了一些情况。

    让我提一下我们什么时候用冒号 Constructor function C++

    1-调用基类构造函数

    1号也可以用在身体上,但当成员是 const .

    但是

    用哪一个做你的工作。

    但是在Matlab中,当你想定义 Constant 必须在中定义的属性 properties 你不能在初始化器/构造函数中这样做。

    classdef NamedConst
       properties (Constant)
          R = pi/180; % Can't define it in constructor body, because it is `Constant properties`
      end
      %class body
    end