【问题标题】:When constructing an array of default objects in MATLAB, why is the first element not constructed as instructed?在 MATLAB 中构造默认对象数组时,为什么第一个元素没有按照说明构造?
【发布时间】:2017-05-07 10:20:24
【问题描述】:

这是一个糟糕的标题,但让我试着解释一下。我有一个类test_class,可以通过以下两种方式之一构建。我可以通过调用test_obj = test_class 创建一个具有默认属性的对象,或者我可以通过调用test_obj_array = test_class([x,y]) 创建一个具有默认属性的对象数组。这是完整的代码:

classdef test_class

    properties
        A;
    end

    properties (Dependent = true)
        B;
    end

    methods

        function obj = test_class(S)

            if nargin == 0
                obj.A = 1;
            else
                x = size(S,1);
                y = size(S,2);
                obj(x,y) = test_class;
            end

        function B_value = get.B(obj)

            B_value = obj.A * 2;

        end

    end

end

现在,当我检查这些对象的属性时:

test_obj_array(1,1).A = []
test_obj_array(1,1).B = []

test_obj_array(1,2).A = 1
test_obj_array(1,2).B = 2
...

为什么没有构造数组中的第一个对象?

现在,通过添加test_obj_array(1,1) = test_class 或稍后修改属性很容易修复,但这是一件容易忘记且难以排除故障的事情。

注意:如果将值数组传递给构造函数,则不会看到此行为,如 MATLAB documentation 中所示。

【问题讨论】:

  • 它没有被构造,因为你从未指示 MATLAB 这样做。通过传递输入参数,您可以绕过数组中第一个对象的无参数构造函数。你打算[x,y] 是什么?输出对象数组的大小?

标签: arrays matlab oop constructor


【解决方案1】:

我不完全确定导致这种行为发生的幕后情况。但是,从MATLAB documentation on initializing object arrays 中,您可以使用以下语法来获得您想要的行为:

test_obj_array(x,y) = test_class;

这将正确调用默认构造函数。

根据文档,上面说

当 MATLAB 调用不带参数的构造函数来初始化对象数组时,会发生以下赋值之一:

  • 如果属性定义指定了默认值,MATLAB 会分配这些 价值观。
  • 如果构造函数在没有输入的情况下赋值 参数,MATLAB 会分配这些值。
  • 如果以上都不是 在适用的情况下,MATLAB 分配空双精度值(即 []) 到财产。

在您的情况下,第二个要点应该适用,但由于某种原因不适用。我在构造函数中设置了一些断点,当对象从外部初始化为数组时(即我上面建议的语法,它有效),为每个非显式构造的对象调用默认 ctor。但是,从 ctor 内部初始化数组时,不会调用默认 ctor。这可能是由于期望每个对象无论如何都需要显式初始化(​​数组语法在文档中的示例中如何工作),所以为什么要这样做两次,但是......我同意你的观点,我认为这是一个错误,或者至少是 Mathworks 的一个糟糕的设计选择。


附带说明,您用来确定数组大小的逻辑(无论如何都不起作用)搞砸了。传递 [3, 5] 会得到一个 1x2 数组,因为 size(S) 是 1x2,而不是 3x5...

【讨论】:

  • size 调用可能是一个问题,但不是出于所述原因。 sizespecifies the dimension 的第二个输入,所以它会返回一个标量。
  • @excaza 是的,这正是我要说的。 size(S,1)size(S,2) 给出输入参数的第一维和第二维的大小。在这种情况下,1x2。看起来OP实际上想要做的是直接使用 S(1) 和 S(2) 。但是这个问题与为什么输出的某些元素未初始化的问题是正交的。如果您尝试我建议的语法,您将看到默认构造函数被适当地调用,这与 OP 的代码不同。
  • 我明白了。我不清楚该声明,似乎您在谈论 size 的返回,而不是构造函数。
  • 我认为发生的事情是,当输入构造函数时,obj 被初始化为test_class 的标量(1 x 1)数组,默认属性来自properties部分(在这种情况下默认为[])。当使用obj(x,y) = test_class 扩展数组时,第一个元素不会重新初始化,因为它不是由数组扩展新创建的。如果你传递一个更大的参数,比如a = test_class([1 2 3]),你可以看到像a(2) 这样的中间元素实际上是由零参数构造函数初始化的。
  • 如果你只是想用默认值初始化一个统一的对象数组,你可能想在构造函数中使用obj = repmat(test_class, [x y])obj = repmat(test_class, S)
猜你喜欢
  • 2019-11-22
  • 2023-03-20
  • 2016-10-16
  • 1970-01-01
  • 2018-10-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多