Customize Parentheses Indexing for Mapping Class
This example shows how to customize parentheses indexing for a class. The
MyMap class stores strings ("keys") that are associated with elements
("values") of a cell array. The class inherits from
matlab.mixin.indexing.RedefinesParen to define custom behavior for
indexing with parentheses. The class supports three customized indexing operations:
returns the value associated with the key.instanceName("keyName")adds a new key and associated value.instanceName("keyName") =valuedeletes the key and its associated value.instanceName("keyName") = []
The full code for the class and its helper function, validateKeys,
is available at the end of the example.
MyMap Class | Explanation |
|---|---|
classdef MyMap... < matlab.mixin.indexing.RedefinesParen | Define |
properties (Access = private)
Keys (:,1) string
Values (:,1) cell
end | The private properties |
methods (Static, Access = public) function obj = empty(varargin) if nargin == 0 obj = MyMap(string.empty(0,1),cell.empty(0,1)); return; end keys = string.empty(varargin{:}); if ~all(size(keys) == [0, 1]) error("MyMap:MustBeEmptyColumnVector",... "The only supported empty size is 0x1."); end obj = MyMap(keys,cell.empty(varargin{:})); end end | Implementation of the static, abstract method |
methods (Access = public) function obj = MyMap(keys_in,values_in) if nargin == 0 obj = MyMap.empty(0,1); return; end narginchk(2,2); if ~all(size(keys_in) == size(values_in)) error("MyMap:InputSizesDoNotMatch",... "The sizes of the input keys and values must match."); end obj.Keys = keys_in; obj.Values = values_in; end end | The constructor accepts the keys and values as input arguments and ensures the arrays are the same size. |
function keys = getKeys(obj) keys = obj.Keys; end function values = getValues(obj) values = obj.Values; end | Two public methods provide read access to the keys and values. |
function varargout = size(obj,varargin) [varargout{1:nargout}] = size(obj.Keys,varargin{:}); end function C = cat(dim,varargin) error("MyMap:ConcatenationNotSupported",... "Concatenation is not supported."); end function lastKey = end(~,~,~) error("MyMap:EndNotSupported",... "Using end with MyMap objects is not supported."); end | Implementation of the abstract methods |
methods (Access = private)
function [keyExists,idx] = convertKeyToIndex(obj,keyCellArray)
arguments
obj
keyCellArray cell {validateKeys}
end
requestedKey = keyCellArray{1};
idx = find(contains(obj.Keys,requestedKey));
keyExists = ~isempty(idx);
end
end | The |
methods (Access = protected) function varargout = parenReference(obj,indexOp) [keyExists,idx] = convertKeyToIndex(obj,indexOp(1).Indices); if ~keyExists error("MyMap:KeyDoesNotExist",... "The requested key does not exist."); end if numel(indexOp) == 1 nargoutchk(0,1); varargout{1} = obj.Values{idx}; else % Additional operations [varargout{1:nargout}] = obj.Values{idx}.(indexOp(2:end)); end end | Implementation of the abstract method
|
function obj = parenAssign(obj,indexOp,varargin) indicesCell = indexOp(1).Indices; [keyExists,idx] = convertKeyToIndex(obj,indicesCell); if numel(indexOp) == 1 value = varargin{1}; if keyExists obj.Values{idx} = value; else obj.Keys(end+1) = indicesCell{1}; obj.Values{end+1} = value; end return; end if ~keyExists error("MyMap:MultiLevelAssignKeyDoesNotExist", ... "Assignment failed because key %s does not exist",... indicesCell{1}); end [obj.Values{idx}.(indexOp(2:end))] = varargin{:}; end | Implementation of the abstract method |
function obj = parenDelete(obj,indexOp) [keyExists,idx] = convertKeyToIndex(obj,indexOp(1).Indices); if keyExists obj.Keys(idx) = []; obj.Values(idx) = []; else error("MyMap:DeleteNonExistentKey",... "Unable to perform deletion. The key %s does not exist.",... indexOp(1).Indices{1}); end end | Implementation of the abstract method |
function n = parenListLength(obj,indexOp,indexingContext) [keyExists,idx] = convertKeyToIndex(obj,indexOp(1).Indices); if ~keyExists if indexingContext == matlab.indexing.IndexingContext.Assignment error("MyMap:MultiLevelAssignKeyDoesNotExist", ... "Unable to perform assignment. Key %s does not exist",... indexOp(1).Indices{1}); end error("MyMap:KeyDoesNotExist",... "The requested key does not exist."); end n = listLength(obj.Values{idx},indexOp(2:end),indexingContext); end end | Implementation of the abstract method
|
Expand for Class and Helper Function Code
Save the code for MyMap and validateKeys in your
MATLAB path. Create an instance of MyMap with an initial list of
three keys and values.
map = MyMap(["apple","cherry","orange"],{1,3,15});
Use the map(" syntax to return
the value corresponding to a specific key.keyName")
map("cherry")ans =
3Use the map(" to add a new key to the array.keyName") =
value
map("banana") = 2; map("banana")
ans =
2Use the map(" to delete a
key and its associated value from the array. Confirm the key is no longer in the
array.keyName") = []
map("orange") = []; map("orange")
Error using MyMap/parenReference (line 88) The requested key does not exist.
See Also
matlab.mixin.indexing.RedefinesParen | matlab.indexing.IndexingOperation