Настройте индексацию круглых скобок для отображения класса

В этом примере показано, как настроить индексацию круглых скобок для класса. MyMap класс хранит строки ("ключи"), которые сопоставлены с элементами ("значения") массива ячеек. Класс наследовался matlab.mixin.indexing.RedefinesParen задавать пользовательское поведение для индексации с круглыми скобками. Класс поддерживает три настроенных операции индексации:

  • instanceName'KeyName' ") возвращает значение, сопоставленное с ключом.

  • instanceName'KeyName' ") = value добавляют новое значение ключа и присваиваемое значение.

  • instanceName'KeyName' ") = [] удаляет ключ и его присваиваемое значение.

Полный код для класса и его функции помощника, validateKeys, доступно в конце примера.

MyMap КлассОбъяснение
classdef MyMap... 
  < matlab.mixin.indexing.RedefinesParen

Задайте MyMap как подкласс RedefinesParen. и реализуйте его абстрактные методы

properties (Access = private)
   Keys (:,1) string
   Values (:,1) cell
end

Частные свойства Keys и Values n-by-1 векторы.

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

Реализация статического, абстрактного метода empty, который создает MyMap объект без ключей или значений.

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

Конструктор принимает ключи и значения как входные параметры и гарантирует, что массивы одного размера.

   function keys = getKeys(obj)
      keys = obj.Keys;
   end
        
   function values = getValues(obj)
      values = obj.Values;
   end

Два открытых метода обеспечивают доступ для чтения к ключам и значениям.

   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

Реализация абстрактных методов size\cat, и end. В этом примере, cat и end не поддерживаются.

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

parenReference, parenAssign, parenDelete, и parenListLength методы используют convertKeyToIndex вспомогательный метод. convertKeyToIndex использование validateKeys гарантировать тот keyCellArray содержит только один ключ. (См. код для validateKeys после конца класса.) convertKeyToIndex возвращает логическое, которое указывает, существует ли входной ключ и, если он делает, индекс ключа.

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

Реализация абстрактного метода parenReference, который обрабатывает выражения индексации ссылки формы instanceName'KeyName' "). Метод берет IndexingOperation экземпляр, как введено. Тот экземпляр, indexOp, включает тип индексации (в этом случае, круглые скобки) и значение индекса от интерпретируемого выражения. parenReference передает индекс в indexOp к convertKeyToIndex чтобы проверить, что ключ существует и, если так, возвращают индекс того ключа idx. Метод затем возвращает значение, которое соответствует ключу. Если существует больше чем одна операция индексации в indexOp, линия пометила "Additional operations" вперед обработкой тех операций к MATLAB®.

   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

Реализация абстрактного метода parenAssign, который обрабатывает выражения индексации присвоения формы instanceName'KeyName' ") = value. Если ключ, на который ссылаются, существует, то метод присваивает значение с правой стороны выражения к тому ключу. Если ключ не существует и существует только один уровень индексации, то ключ и значение добавляются к списку.

   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

Реализация абстрактного метода parenDelete, который обрабатывает выражения индексации удаления формы instanceName'KeyName' ") = []. Если ключ, на который ссылаются, существует, то метод удаляет ключ и его присваиваемое значение. Если ключ не существует, то метод выдает ошибку.

  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

Реализация абстрактного метода parenListLength, который определяет количество значений, чтобы возвратиться из круглых скобок, индексирующих выражения. Метод берет экземпляр matlab.indexing.IndexingContext как введено, чтобы определить, используется ли ссылка в операторе как список аргументов к функции, или в операции присвоения.

 Расширьтесь для кода функции класса и помощника

Сохраните код для MyMap и validateKeys в вашем пути MATLAB. Создайте экземпляр MyMap с первоначальным списком трех ключей и значений.

map = MyMap(["apple","cherry","orange"],{1,3,15});

Используйте карту ("keyName") синтаксис, чтобы возвратить значение, соответствующее определенному ключу.

map("cherry")
ans =

     3

Используйте карту ("keyName") = value добавить новый ключ в массив.

map("banana") = 2;
map("banana")
ans =

     2

Используйте карту ("keyName") = [] удалить ключ и его присваиваемое значение от массива. Подтвердите, что ключ больше не находится в массиве.

map("orange") = [];
map("orange")
Error using MyMap/parenReference (line 88)
The requested key does not exist.

Смотрите также

|