classdef Dog < handle
properties
data;
end
methods
function self = Dog(varargin)
disp("Dog()")
end
function out = new(~)
out = Dog();
out('bark') = 1;
end
end
end
d=Dog()
; 为什么下面打印d.new()
?
Dog()
Dog()
Dog()
如果我超载,它也会绕过subsref
。在控制台中输入d
会给出
ans =
1×114 Dog array with properties:
data
并且没有用d('bark') = 1
复制.
如果我摆脱varargin
,行为就会改变,而是出现错误。还有为什么1x114
?
以下是调用d.new()
时(d = Dog()
之后)发生的情况:
out = Dog();
被调用。此构造函数调用触发"Dog()"的第一个输出
调用out('bark') = 1;
,这将触发以下内容:'bark'
的字符被解释为值[98 97 114 107 ]
。因此,Matlab 将out
大小调整为 114。- 为了构造一个
Dog
对象来填充out
中[98 97 114 107 ]
的位置,Matlab 再次调用构造函数,这次输入参数varargin
等于{ 1 }
。这将触发"Dog()"的第二个输出。 - 为了构造一个
Dog
对象来填充out
中的其他位置,Matlab 再次调用构造函数,这次没有输入参数。这将触发"Dog()"的第三个输出。
此外,subsref
不会被绕过,而只是不被调用,因为您不会以读取方式引用对象。
当你删除varargin
时,你会得到错误,因为不能再用一个输入参数调用构造函数,如上面 2. 下的第二个项目符号中所述。
据我了解,在类方法中,索引表达式始终使用内置的subsasgn
和subsref
,而不是您可能自己编写的重载(自定义)表达式。这样,重载这些函数不会删除类方法访问对象属性的能力。
因此,在您的类方法中,out(i)
访问数组中的第i
个对象out
。这不是out.data(i)
,out
实际上是类Dog
的对象数组。Dog()
创建一个 1x1 数组,您通常将其视为一个对象,但它实际上是一个数组。MATLAB 中的所有内容都是一个数组!
现在out('bark') = 1
.'bark'
,正如 user16372530 的 anwser 所解释的那样,是一个 4 元素数组,数值[98 97 114 107]
。因此,out
从自定义类的 1x1 数组开始,大小调整为 114 个元素的数组,以及您1
分配的 4 个元素。在这里,MATLAB 需要创建一个空元素来填充 113 个新元素,因此调用Dog()
一次并将结果复制到每个元素中。然后它需要将1
转换为您的类,因此调用Dog(1)
执行此操作,并将结果复制到 4 个索引元素。实际上,如 user16372530 在下面的注释中,首先转换1
,然后创建空对象。
如果你想让你的类方法使用重载的索引运算符,你需要显式调用subsasgn
或subsref
,这很丑陋且难以阅读。据我了解,确实没有办法在类方法中使用类对象,因为您实际上打算使用您的类。相同的代码在类方法内部和外部的行为不同。
MATLAB OOP有一些非常有趣的功能,但它也有很多奇怪和不方便的东西。我猜他们尽了最大的努力在以前存在的 MATLAB 数组语法中设计了一个自定义类系统。