2

I am having trouble understanding the behaviour of Matlab when it comes to changing the properties of objects that are set as a property of some other object. Specifically, suppose I have three objects: a parentObject, a childObject and a propertyObject. Of course, in this simple example, these properties seem a bit nonsensical, but I'm writing quite a large program, for which it is useful to group all corresponding methods and properties on these levels.

Now, my definition of these classes is as shown below. The parentObject inherits from dynamicprops to allow it to have an interactively editable list of children. The propertyObject inherits from dynamicprops, because in my program, I need to be able to dynamically add (or delete unused) properties.

classdef parentObject < dynamicprops
    properties
        name 
        children = [];
    end

    methods
        function obj = parentObject(name)
            obj.name = name;
        end
        function obj = addchild(obj, childName)
            obj.children = [obj.children, childObject(childName)];
        end
    end
end
classdef childObject
    properties
        name
        someProperty(1, 1) propertyObject
    end

    methods
        function obj = childObject(name)
            obj.name = name;
        end
    end
end
classdef propertyObject < dynamicprops

    properties
        value1 = 0;
        value2 = 0;
    end
    methods

    end
end

Now in the following interactive session, I am trying to create children objects, and to adjust one of the default values of one of the childrenObject's propertyObject. I'd expect one of the properties, value1, of one of the children to change.

However, this is not the case (see below). Changing one of the children's propertyObject automatically changes the second child's propertyObject, too. What's more, testing to see whether these two propertyObjects are equal yields a positive result. I'd expect the instantiation of a child (and thus its default propertyObject) to yield a unique propertyObject each time. I'm coming from programming in Python and here this, to the best of my knowledge, is the case. Can anyone explain to me where I'm going wrong and how I can get the classes to behave the way I intend them to?

>> parent = parentObject('parent')

parent = 

  parentObject with properties:

        name: 'parent'
    children: []

>> parent.addchild('child1')

ans = 

  parentObject with properties:

        name: 'parent'
    children: [1×1 childObject]

>> parent.addchild('child2')

ans = 

  parentObject with properties:

        name: 'parent'
    children: [1×2 childObject]

>> parent.children(1).someProperty

ans = 

  propertyObject with properties:

    value1: 0
    value2: 0

>> parent.children(2).someProperty

ans = 

  propertyObject with properties:

    value1: 0
    value2: 0

>> parent.children(2).someProperty.value1 = NaN

parent = 

  parentObject with properties:

        name: 'parent'
    children: [1×2 childObject]

>> parent.children(1).someProperty.value1

ans =

   NaN

>> parent.children(1).someProperty == parent.children(2).someProperty

ans =

  logical

   1

P.s., I see that my question has been marked as a duplicate. However, the duplicate question only answers part of my question; the bit that explains how I can get the desired object behaviour. Even though the duplicate question explains that Matlab loads a default object/property only once, it still isn't clear to me why Matlab, upon actively changing this default value for one instance, suddenly changes the property value for all instances. That is, if we cannot change the default value of one instance without changing the value of all instances, what is the purpose of defaulting?

Sam
  • 305
  • 1
  • 8
  • 2
    `childObject.someProperty` is a handle class object. All instances of `childObject` have the **same** instance of a `propertyObject` object as their `someProperty` property. That is, `parent.children(1).someProperty` is the same object as `parent.children(2).someProperty`. Because it's the same object, changing it in one place also changes it everywhere else. This is the problem with handle classes, if you try to make a copy, all you do is reference the same instance. You might want to consider not using handle classes at all, it's always easier without. – Cris Luengo Nov 01 '19 at 04:07
  • Default values for properties are useful, but they just don't work as expected when the value is a handle. See https://www.mathworks.com/help/matlab/matlab_oop/specifying-properties.html#br18hyr – Cris Luengo Nov 01 '19 at 04:12
  • Thanks for the clarification. I get the logic behind the behaviour now, though it is still unclear to me in what situation this behaviour would ever be desirable. I'd like to follow your advice and refrain from using handle classes overall, but I couldn't use the dynamic property setting, then, could I? – Sam Nov 01 '19 at 22:26
  • I don't know why you need it, so I can't suggest an alternative. But you can implement that behaviour quite simply, I think, by overloading the `subsref` and `subsasgn` methods. I would keep a struct as one of the hidden properties, and implement the two methods to read the values from the struct. Or you could keep it simple and just directly use the struct from outside your class: `obj.dyn.some_property = 0`, `obj.dyn.something_else = 1`, etc, with `dyn` a struct property. – Cris Luengo Nov 01 '19 at 22:35
  • For future visitors: this question was answered [here](https://stackoverflow.com/questions/58169408/nested-classdef-with-or-without-handle) and [here](https://stackoverflow.com/questions/49370627/matlab-handle-object-properties-of-unique-objects-refer-to-the-same-object). [question was erroneously reopened and I can’t vote to close again] – Cris Luengo Nov 04 '19 at 14:04

0 Answers0