创建自定义对象数组时输入参数错误不足 [英] Not enough input arguments error when creating an array of custom objects

查看:91
本文介绍了创建自定义对象数组时输入参数错误不足的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我使用值SIDE_NO = 1运行此代码,则效果很好,但是当我将其更改为任何其他值时,它会给我一个错误.发生什么事了?

If I run this code with the value SIDE_NO = 1 it works perfectly, however when I change it to any other value, it gives me an error. What is happening?

输入参数不足.

Not enough input arguments.

CubePiece中的错误(第15行) obj.posX = x;

Error in CubePiece (line 15) obj.posX = x;

Main错误(第21行) cubePieces(x,y)=件;

Error in Main (line 21) cubePieces(x,y) = piece;


主要方法

SIDE_NO = 2;
PIECE_NO = 9;

cubeColors = zeros(SIDE_NO, PIECE_NO);

for s = 1: SIDE_NO
   cimg = Snapshot();
   simg = ScanFace(cimg);
   cubeColors(s,:) = GetColours(simg);
end

for x = 1: SIDE_NO
   for y = 1: PIECE_NO
      piece = CubePiece(x,y,cubeColors(x,y));
      cubePieces(x,y) = piece;
   end
end


CubePiece

classdef CubePiece

properties
    posX      % 1, 2, 3
    posY      % 1, 2, 3
    color     % red, blue, orange, yellow, white, green
    faceCode  % R,L,U,D,F,B
    faceNo    % 1, 2, 3, 4, 5, 6
end

methods
    function obj = CubePiece(x,y,col)
        obj.posX = x;
        obj.posY = y;
        obj.color = col;
        obj.faceNo = x;
        obj.faceCode = obj.getFaceCode(x);

    end

    function code = getFaceCode(~,num)
        if num == 1
            code = 'R';
        elseif num == 2
            code = 'L';
        elseif num == 3
            code = 'U';
        elseif num == 4
            code = 'D';
        elseif num == 5
            code = 'F';
        elseif num == 6
            code = 'B';
        end
    end

   end

end

推荐答案

问题

您的问题是由于以下事实:您不断在循环内将数据追加到数组中(导致数组大小增加). MATLAB需要尝试扩展数组以包含您的数据,同时确保数组保持矩形形状.

The Problem

You issue is due to the fact that when you keep appending data to an array within a loop (causing the array to increase in size). MATLAB needs to attempt to expand the array to contain your data while at the same time ensuring that the array remains rectangular in shape.

所以让我们更仔细地了解正在发生的事情.

So let's look a little closer at what's happening.

当您将x设为1并每次将y递增1时.每次循环时,您都会创建一个新的CubePiece实例.然后,您隐式将新列添加到cubePieces进行存储.

When you're looping with x at 1 and incrementing y by 1 each time. Each time through the loop you create a new CubePiece instance. Then you implicitly add a new column to cubePieces to store it.

cubePieces(x,y) = piece;

我强调隐式,因为您不会预分配 cubePieces为其最终大小([SIDE_NO x PIECE_NO]).因此,如果我们将以下语句放入您的循环中,则可以监控cubePieces的大小.

I emphasize implicit because you don't pre-allocate cubePieces to be it's final size ([SIDE_NO x PIECE_NO]). So if we stick the following statement within your loop, we can monitor the size of cubePieces as it grows.

disp(size(cubePieces));

在遍历y值的同时将x等于1时,您将看到以下条目.

You will see the following entries as you loop through y values while keeping x equal to 1.

1   1
1   2
1   3
...
1   9

您可以看到列数继续增加,直到达到9(PIECE_NO).

As you can see the number of columns continues to increase until we get to 9 (PIECE_NO).

现在,当您到达x = 2时,MATLAB不能仅添加一个条目(一直在这样做),而是必须在整个行中添加 ,因为矩阵/数组不能为不规则形状.所以再次,如果我们观看disp语句的输出,我们将得到.

Now, when you get to x = 2, MATLAB can't just add one more entry (as it has been doing), but rather it must add an entire row because the matrix/array can't be an irregular shape. So again if we watch the output of the disp statement we will get.

2   9
2   9
...
2   9

如果您注意到,这一次并没有通过内部循环更改大小.这是因为MATLAB在第一次通过循环时为整个行填充了8个虚拟"值,因为它要求新行具有9列,但它只知道第一个的值.

If you notice, it's not changing size this time through the inner loop. This is because MATLAB filled in 8 "dummy" values for the entire row on the first pass through the loop since it requires that the new row have 9 columns but it only knows the value of the first one.

问题是,如果不设置值,MATLAB如何填充整个值?答案是(对于对象)MATLAB调用完全填充新行所需的每个元素的默认构造函数(没有输入参数的构造函数).之所以如此,是因为数组的所有成员都必须是同一类型(忽略异构对象).

因此,当您第一次分配给cubePieces(2,1)时. MATLAB 实际上所做的就是这个.

So when you assign to cubePieces(2,1) for the first time. What MATLAB actually does is this.

cubePieces(2,:) = [piece, CubePiece(), CubePiece(), CubePiece()...];

因此,这些空的构造函数给您带来了麻烦.在构造函数中,您无需检查以确保提供了正确的输入,而是只是开始尝试使用它们.显然,这将导致有关输入参数不足的错误.

So it's these empty constructors that are giving you your issue. In your constructor, you don't check to ensure that the proper inputs were provided, but rather you just start trying to use them. This is obviously going to create an error about not enough input arguments.

CubePiece() 

输入参数不足.

Not enough input arguments.

CubePiece中的错误(第13行)

Error in CubePiece (line 13)

obj.posX = x;

obj.posX = x;

13 obj.posX = x;

13 obj.posX = x;


解决方案

您想要做的是优雅地处理没有输入参数到构造函数的情况,并提供有效的默认"对象.


A Solution

What you want to do is gracefully handle the case where there are no inputs arguments to the contstructor and provide a valid "default" object.

您可以通过返回而无需分配任何属性(if nargin == 0; return; end)来执行此操作.或者,如果您想要各种属性的默认值,则可以在类定义的properties块中指定这些默认值.

You can do this by either returning without assigning any of the properties (if nargin == 0; return; end). Or if you want default values for the various properties, you can specify those defaults in the properties block of the class definition.

classdef CubePice

    properties
        posX = 1
        posY = 1
        color = 'red';
        faceCode = 'R';
        faceNo = 1
    end

    methods
        function obj = CubePiece(x,y,col)
            if nargin == 0
                return;
            end

            obj.posX = x;  

            % Do other assignments
        end
    end
end


更好的解决方案(预分配)

更好的解决方案是实际上预先分配要分配的变量,以使MATLAB不会不断改变其大小.这具有一些性能优势.有几种方法可以做到这一点


A Better Solution (Pre-allocation)

The better solution is to actually pre-allocate the variable that you are assigning to so that MATLAB isn't continually altering the size of it. This has some performance advantages. There are a few ways to do this

repmat

repmat

如果您实际上想要CubePiece对象的2D数组,则可以实际将CubePiece对象的2D数组预先分配为适当的大小.您可以通过将repmat应用于类的单个实例来实现此目的.

If you actually want a 2D array of CubePiece objects you can actually pre-allocate your 2D array of CubePiece objects to be the proper size. You can do this by using repmat applied to a single instance of your class.

template = CubePiece(1,1,1);
cubePieces = repmat(template, [SIDE_NO, PIECE_NO]);

现在,您将拥有一个二维对象数组(从技术上讲,所有对象都是相同对象),MATLAB无需对该数组进行任何动态扩展,并尝试猜测您使用的默认值要使用.

Now you will have a 2D array of objects (technically all handles to the same object) and MATLAB won't have to do any dynamic expansion of this array and try to guess what default values you want to use.

一次扩展"方法

如果您不介意MATLAB调用默认构造函数(并且已经设置了类构造函数来处理此问题),您可以可以通过简单地在最大的行和列上分配值来初始化此数组首先,它将立即将数组扩展到最大大小.

If you don't mind MATLAB calling the default constructor (and you've setup your class constructor to handle this) you could initialize this array by simply assigning the value at the largest row and column first which will expand the array to its maximum size at once.

cubePieces(SIDE_NO, PIECE_NO) = CubePiece(1,1,1);

size(cubePieces)

    2   9

单元格阵列

您还可以在创建过程中将对象存储在单元格数组中.

You could also store your objects within a cell array during creation.

cubePieces = cell(SIDE_NO, PIECE_NO);
for x = 1:size(cubePieces, 1)
    for y = 1:size(cubePieces, 2)
        cubePieces{x,y} = CubePiece(x, y, cubeColors(x,y))
    end
end

然后再根据需要使用 cell2mat 将单元格转换为2D数组.

Then afterwards if you want, you can use cell2mat to convert the cell into a 2D array.

现在,整篇文章都在讨论自定义MATLAB类;但是,这实际上也适用于 all MATLAB内置类.

Now this whole post has been talking about custom MATLAB classes; however, this really applies to all MATLAB built-in classes as well.

例如,一个double s的数字数组.

Take for example a numeric array of doubles.

x = 1:5

   1     2     3     4     5

现在让我们在x(2,1)处添加一个元素.

Now let's add an element at x(2,1).

x(2,1) = 6

   1     2     3     4     5
   6     0     0     0     0

很显然,double的默认值为0,因为MATLAB会将所有未指定的值都填充为0.

Clearly, the default value of a double is 0 because MATLAB filled in all the unspecified values with 0.

我们可以对单元格数组执行相同的操作,其中默认值为空数组([]).

We can do the same for a cell array, where the default value is an empty array ([]).

y = num2cell(1:5)

  [1]    [2]    [3]    [4]    [5]

y{2,1} = 6;

  [1]    [2]    [3]    [4]    [5]
  [6]     []     []     []     []

有关此行为的更多信息,请参见

More information about this behavior can be found at this page.

在动态扩展对象的二维数组(无论它们是内置数据类型还是自定义类)时,MATLAB必须填充缺失值以保持矩形形状.用于填写未指定值的默认"值取决于数据类型.对于自定义类,通过调用不带参数的构造函数来创建此默认"数据类型.通过显式预分配多维数组,可以避免这种默认行为.

When you are dynamically expanding a two-dimensional array of objects (whether they are built-in datatypes or custom classes), MATLAB has to fill in missing values in order to maintain a rectangular shape. The "default" value used to fill in the unspecified values depends on the datatype. For custom classes, this "default" datatype is created by calling the constructor with no arguments. This default behavior can be avoided by explicitly pre-allocating your multi-dimensional arrays.

这篇关于创建自定义对象数组时输入参数错误不足的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆