%% Customize Dot Indexing in a Scalar Class
% This example shows how to customize dot indexing operations in the ScalarStructClass. Instances of ScalarStructClass behave much like structs. Users can dynamically add fields and associated values like a struct, but the class also serves as a base to which additional properties and methods can be added.
% The class inherits from matlab.mixin.Scalar, which means its instances are scalar objects. The only possible array size is 1-by-1, and the instances cannot be concatenated. The class also inherits from matlab.mixin.indexing.RedefinesDot and implements its abstract methods to handle dot indexing operations:
% dotReference: Handles dot references into the private AddedFields property. The syntax instance.fieldname returns the value assigned to the referenced field.
% dotAssign: Adds a new field and corresponding value to the AddedFields property. The syntax instance.fieldname = value adds the field and its corresponding value.
% dotListLength: Determines the number of values to return from dot indexing expressions that return values from or assign values to a comma-separated list.
% The class also defines the getAddedFields method, which returns a list of all fields and corresponding values.
%
%% ScalarStructClass Code
% classdef ScalarStructClass < matlab.mixin.indexing.RedefinesDot & ...
%     matlab.mixin.Scalar
%
%     properties (Dependent, SetAccess=private)
%         FieldNames
%     end
%
%     properties (Access=private)
%         AddedFields struct
%     end
%
%     methods
%         function out = get.FieldNames(obj)
%             out = string(fieldnames(obj.AddedFields));
%         end
%     end
%
%     methods (Access=public)
%         function obj = ScalarStructClass(fieldName,fieldValue)
%             if nargin == 1
%                 obj.AddedFields = fieldName;
%                 return;
%             end
%             obj.AddedFields = struct(fieldName,fieldValue);
%         end
%
%         function out = getAddedFields(obj)
%             out = obj.AddedFields;
%         end
%     end
%
%     methods (Access=protected)
%         function varargout = dotReference(obj,indexOp)
%             [varargout{1:nargout}] = obj.AddedFields.(indexOp);
%         end
%
%         function obj = dotAssign(obj,indexOp,varargin)
%             [obj.AddedFields.(indexOp)] = varargin{:};
%         end
%
%         function n = dotListLength(obj,indexOp,indexContext)
%             n = listLength(obj.AddedFields,indexOp,indexContext);
%         end
%     end
% end
%
%
%% Use a ScalarStructClass Instance
% Construct a ScalarStructClass instance with one field and a corresponding value.

myStructClass = ScalarStructClass("Field1",75)

%
% Add a second field to the instance using dot assignment. The dotAssign method accepts an IndexingOperation object, which describes the type of indexing operation (Dot) and the name of the field, and a second argument that contains the value of the new field.

myStructClass.Field2 = 10;

%
% Use dot notation to verify the value of Field2. Like dotAssign, the dotReference method accepts an IndexOperation object that identifies what field to access.

myStructClass.Field2

%
% Use getAddedFields to see the full list of fields and values.

myStructClass.getAddedFields

%
% ScalarStructClass also supports comma-separated list assignment and reference. Add a third field to myStructClass that contains a cell array.

myStructClass.CellArray = {3 4};

%
% Access the CellArray field. The class calls the dotReference method and returns multiple outputs.

[v1,v2] = myStructClass.CellArray{:}

%
% Assign multiple new values to the CellArray field. Because the assignment operation begins with a dot reference and ends with a brace index, the class calls the dotListLength method in addition to dotAssign to handle the assignment operation.

[myStructClass.CellArray{:}] = deal(5,6);
myStructClass.CellArray

% Copyright 2020 The MathWorks, Inc.