%% Customize Parentheses Indexing
% The ArrayWithLabel class has two properties: ContainedArray and Label. ArrayWithLabel customizes parentheses indexing into ContainedArray by inheriting from matlab.mixin.indexing.RedefinesParen and implementing all of its abstract methods:
% parenReference: Handles parentheses indexing into ContainedArray.
% parenDelete: Deletes parentheses-indexed elements of ContainedArray.
% parenAssign: Assigns values to the indexed elements of ContainedArray. The right-hand side of the assignment expression must be an instance of ArrayWithLabel.
% parentListLength: Determines the number of values to return from parentheses indexing operations on ContainedArray.
% cat: Concatenates the ContainedArray property of one or more instances of the class.
% empty: Returns an instance of the class with an empty ContainedArray.
% size: Returns the dimensions of ContainedArray.
% ArrayWithLabel also provides two public methods:
% value: Displays the indexed values of ContainedArray.
% sum: Calculates the sum of the indexed values of ContainedArray.
%
%% ArrayWithLabel Class Code
% classdef ArrayWithLabel < matlab.mixin.indexing.RedefinesParen
%
%     properties (Access=private)
%         ContainedArray
%     end
%
%     properties (Access=public)
%         Label
%     end
%
%     methods
%         function obj = ArrayWithLabel(val)
%             obj.ContainedArray = val;
%         end
%     end
%
%     methods (Access=protected)
%         function varargout = parenReference(obj,indexOp)
%             obj.ContainedArray = obj.ContainedArray.(indexOp(1));
%             if isscalar(indexOp)
%                 varargout{1} = obj;
%                 return;
%             end
%             % Syntax for forwarding indexing operations
%             [varargout{1:nargout}] = obj.(indexOp(2:end));
%         end
%
%         function obj = parenAssign(obj,indexOp,varargin)
%             if isscalar(indexOp)
%                 assert(nargin==3);
%                 rhs = varargin{1};
%                 obj.ContainedArray.(indexOp) = rhs.ContainedArray;
%                 return;
%             end
%             [obj.(indexOp(2:end))] = varargin{:};
%         end
%
%         function n = parenListLength(obj,indexOp,ctx)
%             if numel(indexOp) <= 2
%                 n = 1;
%                 return;
%             end
%             containedObj = obj.(indexOp(1:2));
%             n = listLength(containedObj,indexOp(3:end),ctx);
%         end
%
%         function obj = parenDelete(obj,indexOp)
%             obj.ContainedArray.(indexOp) = [];
%         end
%     end
%
%     methods (Access=public)
%         function out = value(obj)
%             out = obj.ContainedArray;
%         end
%
%         function out = sum(obj)
%             out = sum(obj.ContainedArray,"all");
%         end
%
%         function out = cat(dim,varargin)
%             numCatArrays = nargin-1;
%             newArgs = cell(numCatArrays,1);
%             for ix = 1:numCatArrays
%                 if isa(varargin{ix},'ArrayWithLabel')
%                     newArgs{ix} = varargin{ix}.ContainedArray;
%                 else
%                     newArgs{ix} = varargin{ix};
%                 end
%             end
%             out = ArrayWithLabel(cat(dim,newArgs{:}));
%         end
%
%         function varargout = size(obj,varargin)
%             [varargout{1:nargout}] = size(obj.ContainedArray,varargin{:});
%         end
%     end
%
%     methods (Static, Access=public)
%         function obj = empty()
%             obj = ArrayWithLabel([]);
%         end
%     end
% end
%
%
%% Use an ArrayWithLabel Instance
% Construct an ArrayWithLabel object with a 2-by-2 matrix, and assign a string to the Label property.

a = ArrayWithLabel([2 3; 5 7]);
a.Label = "primes"

%
% Display the first column of the array. parenReference takes a and an instance of IndexingOperation as arguments. indexOp identifies the type of reference (Paren) and the indices being referenced. parenReference retrieves the elements corresponding to those indices and then forwards the value method call to MATLAB. (The comment in the code identifies the line in parenReference that forwards additional operations after the initial parentheses indexing.)

a(:,1).value

%
% Create a new instance b of ArrayWithLabel with a 1-by-2 vector. Assign the values of b to the second row of the array in a. The parenAssign method uses the indices on the left-hand side of the assignment to determine which elements of a to replace.

b = ArrayWithLabel([11 13]);
a(2,:) = b;
a.value

%
% Use the sum method to find the sum of the values in the second column.

a(:,2).sum

%
% Copyright 2020 The MathWorks, Inc.