divB
divB

Reputation: 973

Property initialization in MATLAB

In MATLAB there are two ways to initialize its properties. Either directly in the properties:

classdef A
    properties
       foo = 'bar';
    end
end

or by explicitly defining a constructor:

classdef B
    properties
        foo;
    end

    methods this = B()
        this.foo = 'bar';
    end
end

Which one is the more preferable way?

(I am asking because there is a similar case in C++ where the preferred way is to initialize the member variables with a colon after the constructor rather than assigning variables within the constructor).

Upvotes: 2

Views: 458

Answers (2)

Sam Roberts
Sam Roberts

Reputation: 24117

In most cases, the two methods behave the same, and the choice is just a preference depending on which you find clearer/easier to maintain etc.

But they are not the same, and there are cases where you will get yourself in trouble if you aren't aware of the differences.

The essential difference is that properties that are initialised in the constructor are initialised separately each time an object is constructed, whereas properties that are initialised in the properties block with a default value are initialised once, when the class definition is first read. The default value in a properties block is the default value of the class, not of the object; and (using reflection) you can query that default value even if no instance of the class has yet been instantiated.

In most cases, this makes no difference - but when the initial value is a handle object, or the output of a non-determinate function it does. So consider the following two classes:

classdef A
    properties
        foo
    end
    methods
        function obj = A
            obj.foo = containers.Map;
        end
    end
end

classdef B
    properties
        foo = containers.Map
    end
end

Note that containers.Map is a handle class.

In class A, every time you create a new instance of A you get a new/different containers.Map for its foo. In B, every instance of B gets the same containers.Map for its foo, as the property is initialised only once, the first time the class definition is read. So if you modify foo for any object of class B, that change is propagated to all other instances of class B, as you can see:

>> a1 = A; a2 = A; a1.foo('greeting') = 'hello'; a2.foo('greeting') = 'bonjour';
>> a1.foo('greeting'), a2.foo('greeting')
ans =
    'hello'
ans =
    'bonjour'
>> b1 = B; b2 = B; b1.foo('greeting') = 'hello'; b2.foo('greeting') = 'bonjour';
>> b1.foo('greeting'), b2.foo('greeting')
ans =
    'bonjour'
ans =
    'bonjour'
>> % Note that b1.foo has changed as a result of setting b2.foo

This point about handle classes as default values often trips people up; but the behaviour is not specific to handle classes. For example, consider the following variation:

classdef A
    properties
        foo
    end
    methods
        function obj = A
            obj.foo = datetime('now');
        end
    end
end

classdef B
    properties
        foo = datetime('now')
    end
end

Here A will store the creation time of each object, whereas B will store the time at which the class was first initialised, for all objects, no matter when they were created.

In case you find this behaviour confusing, see https://undocumentedmatlab.com/blog/handle-object-as-default-class-property-value, and particularly the comment thread underneath that article, for a discussion of the issue, and an explanation for the reasons MATLAB is designed in this way.


Edit: Great follow up question in the comments, regarding the behaviour of clear and its relation to this issue.

Using the second implementation of the classes above (with datetime), look at the following:

>> a = A; b = B; datestr(a.foo), datestr(b.foo)
ans =
    '01-Sep-2018 18:59:30'
ans =
    '01-Sep-2018 18:59:30'
>> clear variables
>> a = A; b = B; datestr(a.foo), datestr(b.foo)
ans =
    '01-Sep-2018 18:59:48'
ans =
    '01-Sep-2018 18:59:30'
>> clear classes
>> a = A; b = B; datestr(a.foo), datestr(b.foo)
ans =
    '01-Sep-2018 18:59:57'
ans =
    '01-Sep-2018 18:59:57'

So we first of all create an A and a B, and display their foos, and they both show the same time. Then we wait a little while, do clear variables, and we do it again. Note that the foo from A is the new time, and the foo from B is still the same as before. Finally we wait a little more time, we do clear classes, and we do it again. This time both A and B have the new time.

Why? Because clear variables merely removes references to the variables from the workspace. The class definition of B is not cleared, so when we create another B, it still uses the value from when the class definition was first read. clear classes, by contrast, also removes the class definition, so when we later construct a new B, it gets that time, as the class definition is then reread. All this is irrelevant to A, as foo is just given a value at construction time.

Note that clear classes clears all class definitions: you can clear the definition of only class B using clear B.

Upvotes: 2

Seyfi
Seyfi

Reputation: 1980

It is on your choice except for some cases.

Let me mention when we use the colon in Constructor function inC++:

1- Calling base class constructors

2- Initializing member variables before the body of the constructor executes.

No.#1 can be also used in the body but we should use the colon in No.#2 when the member is const.

BUT

But here is Matlab, with its own language syntax and structure.

Use which one do your job.

But here in Matlab when you want to define Constant properties you MUST define it in properties part and you can't do it in initializer/constructor function.

classdef NamedConst
   properties (Constant)
      R = pi/180; % Can't define it in constructor body, because it is `Constant properties`
  end
  %class body
end

Upvotes: 0

Related Questions