0

I am going to define a class in MATLAB called "Node" which is supposed to be a node of a tree structure. I have a variable inside it called "NodeList" which is supposed to be a list of sub nodes.
Here is what I have defined:

classdef Node
properties
    Title   string                  %name
    NodeType Type_Node              %enum Design/Variation
    NodeList    cell{Node}        %list of sub nodes
    RelationType    Relation        %enum AND/OR
    ImportanceFactor    float       %float [0  1]
    NodeIndex   {mustBePositive}    %int for drawing the tree
end
methods
    function obj=Node(title,nodetype,nodelist,relation,impactfactor,nodeindex)
        obj.Title=title;
        obj.NodeType=nodetype;
        obj.NodeList=nodelist;
        obj.RelationType=relation;
        obj.ImportanceFactor=impactfactor;
        obj.NodeIndex=nodeindex;
    end
end
end 

While instantiating the class I am getting this error message:

Error setting default value of property 'NodeList' of class 'Node'. The 'Node' class 
definition uses an instance of itself directly
or indirectly as the default value for the 'NodeList' property. This is not allowed.

First, please let me know whether the syntax I have used to define the class is correct or not.

Then, I would appreciate any suggestions to make list of instances of a class.

Third, how can I nest a list of instances of the very class inside itself?

beaker
  • 16,331
  • 3
  • 32
  • 49
RDS
  • 9
  • 5

1 Answers1

3

Try this as a next step. (I simplified the class, for my convenience)

classdef Node < handle
properties
    Title      string     %name
    NodeList   Node       %list of sub nodes
end
properties (Constant = true)
    NullNode = Node();
end
methods
    function obj=Node(varargin)
        switch nargin
            case 2
                obj.Title=varargin{1};
                obj.NodeList=varargin{2};
            case 0
                obj.Title = '';
                obj.NodeList = obj;
        end
    end
end
end

Now these all work:

nFirst     = Node()
nOther     = Node('name', nFirst )
nWithAList = Node('list', [nFirst, nOther])

Changes that I made:

  1. The NodeList validator is only to the Node class, rather than cell{Node}. This still allows a standard array of the class. (You can separately set size restrictions on the array if you want. [1])
  2. I added a 0-argument constructor, which is self-referential. (I might also use a Constant NullNode object to put in here, depending on what makes sense in the project. Sample is defined in the code.)
  3. I derived this class from handle. (This is not strictly needed to address your original question. However, based on the context of the sample code, I suspect this is closer the behavior you will expect.)

[1] https://www.mathworks.com/help/matlab/matlab_oop/defining-properties.html (See "Property Validation Syntax")

Pursuit
  • 12,285
  • 1
  • 25
  • 41
  • Good solution (+1), but I don't agree with the statement "Most of the time, if you need to use the Matlab Object-oriented notation, this [derive from handle] is what you want." You should only derive from `handle` if the object references a resource that cannot be copied (e.g. a file). Sometimes it is useful to emulate the behaviour you get in other languages when you use pointers, but I think there are better ways to accomplish that. Mostly, data is data and can be copied, and thus should not be stored in a handle class. – Cris Luengo Sep 29 '22 at 19:24
  • Fair enough. I was applying a biased opinion into the post. However, I still think I'm right. :) Most Matlab projects that need classes (specifically including the the one in the original post) are performing some data-structure type operations, which often break if they do not inherit from handle. For the common operations where data-is-data and copies are fine, I find that most people use structures or (my favorite) data tables. Moreover, most people learn OO concepts in something like Java. The handle behavior is closer to what is expected. That said, I'll clean that up in the post. – Pursuit Sep 29 '22 at 19:52
  • Thank you @Pursuit, may I also ask for your suggestion on how to iterate through all these nodes? – RDS Sep 29 '22 at 20:42
  • 1
    I'm with @CrisLuengo. Normal MATLAB behaviour is non-`handle`. Any time you make something a `handle`, you risk confusion for ordinary MATLAB users. Not for nothing is the brand new `dictionary` type non-`handle` whereas the thing it is designed to replace (`containers.Map`) was a `handle`. – Edric Sep 30 '22 at 07:47
  • @Edric I’m glad to hear the new `dictionary` is not a handle type. That always bothered me about `containers.Map`! – Cris Luengo Sep 30 '22 at 12:55
  • Hmm, is there a canonical post somewhere describing when `handle` is required/not-required, and also when it is recommended/not-recommended? I can _feel_ the right answer for a few circumstances, but I'm not sure I can express differences clearly. – Pursuit Oct 01 '22 at 22:49