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()
; why does d.new()
print below?
Dog()
Dog()
Dog()
It also bypasses subsref
if I overload it. Entering d
in console gives
ans =
1×114 Dog array with properties:
data
and isn't reproduced with d('bark') = 1
.
The behavior changes if I get rid of varargin
, instead there's an error. Also why 1x114
?
CodePudding user response:
Here is what's happening when calling d.new()
(after d = Dog()
):
out = Dog();
is invoked. This constructor call triggers the first output of "Dog()"out('bark') = 1;
is invoked, which triggers the following:- The characters of
'bark'
are interpreted as values[98 97 114 107 ]
. Consequently, Matlab resizesout
to a size of 114. - To construct a
Dog
object to fill positions[98 97 114 107 ]
inout
, Matlab calls the constructor again, this time with the input argumentvarargin
equal to{ 1 }
. This triggers the second output of "Dog()". - To construct a
Dog
object to fill the other positions inout
, Matlab calls the constructor again, this time with no input argument. This triggers the third output of "Dog()".
- The characters of
Furthermore, subsref
is not bypassed, but simply not called, as you do not refer to the object in a reading manner.
And when you remove varargin
, you get the error, because the constructor cannot be called anymore with one input argument, as explained in the second bullet point under 2. above.
CodePudding user response:
As I understand it, within class methods, indexing expressions always use the built-in subsasgn
and subsref
, not the overloaded (customized) one you might write yourself. This is so that overloading these functions doesn't remove the ability of class methods to access object properties.
So, within your class method, out(i)
accesses the i
th object in the array out
. This is not out.data(i)
, out
is really an array of objects of class Dog
. Dog()
creates a 1x1 array, which you would normally think of as an object, but it really is an array. Everything in MATLAB is an array!
Now for out('bark') = 1
. 'bark'
, as explained by user16372530's anwser, is a 4-element array, with numeric values [98 97 114 107]
. Thus out
, which starts off as a 1x1 array of your custom class, is resized to an array of 114 elements, and to 4 of those elements you assign 1
. Here, MATLAB needs to create an empty element to fill out the 113 new elements, so calls Dog()
once and copies the result to each of those elements. Then it needs to convert 1
to your class, so calls Dog(1)
to do so, and copies to result to the 4 indexed elements. Actually, as indicated by
user16372530 in a comment below, first 1
is converted and then the empty object is created.
If you want your class method to use the overloaded indexing operator, you need to explicitly call subsasgn
or subsref
, which is ugly and hard to read. There really is no way, as far as I understand it, to use class objects inside the class methods as you actually intend your class to be used. The same code behaves differently inside a class method and outside of it.
MATLAB OOP has some really interesting features, but it also has a lot of weird and inconvenient things. I guess they did their best designing a custom class system within the previously existing MATLAB array syntax.