【问题标题】:Matlab: Multiply assignment to objects without loopsMatlab:对没有循环的对象进行乘法赋值
【发布时间】:2014-11-04 10:23:49
【问题描述】:

我寻找了几天的解决方案,但我被困住了。 我有一个简单的对象类:

classdef GRIDCELL < handle    
properties
    rho
end

methods
    %% Constructor
    function obj = GRIDCELL(rho) 
        if nargin ~= 0 % Allow nargin == 0 syntax
            obj.rho = rho;
        end
    end
end
end

例如,我用

创建我的对象
G(1:3) = GRIDCELL(2)

现在,我想更新所有单元格中的值 rho。但不幸的是,这不起作用

C = {11 22 33};
[G(1:3).rho] = C{:};

如果我现在证明这一点,所有值都只会被 C 中的 LAST 值覆盖。我真的不明白 :(

G(1:3).rho

ans =

    33

ans =

   33

ans =

    33

内置交易的结果相同。拜托,我搜索了一种简单快捷的方法来做到这一点,没有像“num2cell”这样的循环或类似的东西。

【问题讨论】:

  • 我没有测试你的类代码,但如果你不使用它,那么它会按预期分发值或C。但是我有一种预感,也许问题是您的类正在创建对同一个对象的多个引用,因此,如果您为其中任何一个分配一个值,您就是将该值分配给所有这些引用,因为它们实际上都只是引用相同的记忆。
  • 也许试试for i = 1:3 G(i) = GRIDCELL(2); end 看看是否还有同样的效果?
  • 好的,这适用于这种情况:)。但是我在我的真实模型中有一个对象数组,例如,我使用for i = 1:3 G(i,2) = GRIDCELL(2); end 创建第二列。在这种情况下,所有值都被 C ^^ 的第一个值覆盖。这有点好笑-.-。我认为,它又是多个参考。我怎么能改变这个,我应该改变我的类构造函数吗?
  • 我无法想象为什么G(i,2)G(i) 有任何不同...除非您可能必须首先初始化G?在循环之前尝试G = zeros(3, 2)
  • 我现在用for i = 1:3 for j = 1:3 G(i,j) = GRIDCELL(2); end end 试了一下。这现在有效。所以这是一个选项,我必须一个接一个地创建对象。但还有其他可能吗?

标签: matlab class object


【解决方案1】:

问题在于您初始化对象数组的方式。举个例子:

MyClass.m

classdef MyClass < handle    
    properties
        x
    end
    methods
        function obj = MyClass(x) 
            if nargin ~= 0
                obj.x = x;
            end
        end
    end
end

现在比较以下几种初始化对象数组的方式:

  1. 在您的情况下,您创建了一个对象数组,其中所有对象都具有相同的句柄(它们引用内存中的相同对象)。

    >> clear c
    
    % one object is created, and the same handle assigned to c(1), c(2), and c(3)
    >> c(1:3) = MyClass(10)
    c = 
      1x3 MyClass array with properties:
    
        x
    
    % test handle equality
    >> c(1) == c(2)   % same for c(1) == c(3) and c(2) == c(3)
    ans =
         1
    
    % changing one object is reflected in all of them
    >> c(1).x = 1;
    >> c(2).x
    ans =
         1
    
  2. 你打算写的内容如下(见the docs):

    >> clear c
    
    % c(3) is first created (with x=10),
    % then x(1) and x(2) are default initialized
    >> c(3) = MyClass(10)
    c = 
      1x3 MyClass array with properties:
    
        x
    
    % separate objects
    >> c(1) == c(2)
    ans =
         0
    
    % objects are independent
    >> c(1).x = 1;
    >> c(2).x
    ans =
         []
    
  3. 如果您愿意,也可以在使用变量c 之前先定义它:

    >> c = MyClass.empty(3,0);
    >> c(3) = MyClass(10);
    

    >> c = MyClass.empty(3,0);
    >> for i=1:3, c(i) = MyClass(i); end    % or i=3:-1:1
    

    然后你可以说使用逗号分隔列表语法为所有对象分配属性x

    >> xx = {1,2,3};
    >> [c.x] = xx{:};    % or [c.x] = deal(xx{:});
    >> c(:).x
    ans =
         1
    ans =
         2
    ans =
         3
    

【讨论】:

  • 这里有一个相关的帖子:stackoverflow.com/a/2510523/97160(注意第三点关于将repmat与句柄类对象一起使用)
  • 当然,这不是值类的问题(与句柄类相反):mathworks.com/help/matlab/matlab_oop/…
  • 感谢您的详细解释。但是还有一个问题,如果我想使用一个对象数组:G = GRIDCELL.empty(3,3,0)。现在,如果我想定义它们,我会得到一个错误:for i=1:3 for j=1:3 G(i,j) = GRIDCELL(2); end end Attempt to grow array along ambiguous Dimension。我需要这个数组。
  • 我有解决这个问题的办法。我没有使用G = GRIDCELL.empty(3,3,0),而是分配了最高的对象:G(3,3) = GRIDCELL(2)。所以我在 G(3,3) 中得到一个值,而其他对象 G(1:2, 1:2) 刚刚创建。但我不明白,为什么 empty-command 不能这样做
  • 你可以写G = GRIDCELL.empty(3,0) 甚至G = GRIDCELL.empty(0,0) 都没关系。如果要使用G = GRIDCELL.empty(3,3,0),则必须将第一个对象指定为:G(i,j,1) = GRIDCELL(2)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-19
  • 1970-01-01
  • 1970-01-01
  • 2014-12-19
相关资源
最近更新 更多