exponenta event banner

Определение суперкласса интерфейса

Интерфейсы

Свойства и методы, определенные классом, образуют интерфейс, определяющий взаимодействие пользователей класса с объектами класса. При создании группы связанных классов интерфейсы определяют общий интерфейс для всех этих классов. Фактические реализации интерфейса могут отличаться от одного класса к другому.

Рассмотрим набор классов, предназначенных для представления различных типов графов. Все классы должны реализовывать Data содержит данные, используемые для создания графа. Однако форма данных может значительно отличаться от одного типа графа к другому. Каждый класс может реализовать Data по-разному.

Те же различия относятся и к методам. Все классы могут иметь draw метод, который создает граф, но реализация этого метода изменяется с типом графа.

Основная идея класса интерфейса заключается в определении свойств и методов, которые каждый подкласс должен реализовать без определения фактической реализации. Этот подход позволяет применять согласованный интерфейс к группе связанных объектов. При добавлении новых классов интерфейс остается прежним.

Графики реализации класса интерфейса

В этом примере создается интерфейс для классов, используемых для представления специализированных графиков. Интерфейс является абстрактным классом, который определяет свойства и методы, которые подклассы должны реализовать, но не указывает, как реализовать эти компоненты.

Этот подход обеспечивает использование согласованного интерфейса при обеспечении необходимой гибкости для реализации внутренней работы каждого специализированного подкласса по-разному.

В этом примере папка пакета содержит интерфейс, производные подклассы и функцию утилиты:

+graphics/GraphInterface.m % abstract interface class
+graphics/LineGraph.m      % concrete subclass

Свойства и методы интерфейса

graph класс задает следующие свойства, которые должны быть определены подклассами:

  • Primitive - дескриптор графического объекта, используемого для реализации специализированного графа. Пользователю класса нет необходимости обращаться к этим объектам напрямую, поэтому это свойство имеет protected SetAccess и GetAccess.

  • AxesHandle - Ручка осей, используемых для графика. Специализированное graph объекты могут задавать свойства объектов осей. Это свойство имеет protected SetAccess и GetAccess.

  • Data - Все подклассы GraphInterface класс должен хранить данные. Тип данных различается, и каждый подкласс определяет механизм хранения. Пользователи подкласса могут изменять значения данных, чтобы это свойство имело права открытого доступа.

GraphInterface именует три абстрактных метода, которые должны реализовывать подклассы. GraphInterface класс также предлагает в комментариях, что каждый конструктор подкласса должен принимать данные печати и пары имя свойства/значение свойства для всех свойств класса.

  • Конструктор подкласса - принимает пары данных и P/V и возвращает объект.

  • draw - используется для создания примитива чертежа и визуализации графика данных в соответствии с типом графа, реализуемого подклассом.

  • zoom - Реализация метода масштабирования путем изменения осей CameraViewAngle собственность. Интерфейс предлагает использование camzoom функция для обеспечения согласованности между подклассами. Кнопки масштабирования, созданные addButtons статический метод использует этот метод в качестве обратного вызова.

  • updateGraph - Метод, вызываемый set.Data для обновления выводимых на печать данных всякий раз, когда Data изменения свойств.

Проектирование классов руководств по интерфейсам

Пакет классов, производный от GraphInterface абстрактный класс реализует следующие варианты поведения:

  • Создание экземпляра специализированного GraphInterface объект (объект подкласса) без визуализации графика

  • Указание каких-либо или ни одного из свойств объекта при создании специализированного GraphInterface объект

  • Изменение любого свойства объекта автоматически обновляет отображаемый в данный момент график

  • Разрешение каждого специализированного GraphInterface объект для реализации любых дополнительных свойств, которые требуются для предоставления пользователям класса контроля над этими характеристиками.

Определение интерфейса

GraphInterface - абстрактный класс, определяющий методы и свойства, используемые подклассами. Комментарии в абстрактном классе описывают предполагаемую реализацию:

classdef GraphInterface < handle
   % Abstract class for creating data graphs
   % Subclass constructor should accept
   % the data that is to be plotted and
   % property name/property value pairs
   properties (SetAccess = protected, GetAccess = protected)
      Primitive
      AxesHandle
   end
   properties
      Data
   end
   methods (Abstract)
      draw(obj)
      % Use a line, surface,
      % or patch graphics primitive
      zoom(obj,factor)
      % Change the CameraViewAngle
      % for 2D and 3D views
      % use camzoom for consistency
      updateGraph(obj)
      % Update the Data property and
      % update the drawing primitive
   end
   
   methods
      function set.Data(obj,newdata)
         obj.Data = newdata;
         updateGraph(obj)
      end
      function addButtons(gobj)
         hfig = get(gobj.AxesHandle,'Parent');
         uicontrol(hfig,'Style','pushbutton','String','Zoom Out',...
            'Callback',@(src,evnt)zoom(gobj,.5));
         uicontrol(hfig,'Style','pushbutton','String','Zoom In',...
            'Callback',@(src,evnt)zoom(gobj,2),...
            'Position',[100 20 60 20]);
      end
   end
end 

GraphInterface класс реализует метод набора свойств (set.Data) для мониторинга изменений в Data собственность. Альтернативой является определение Data свойство как Abstract и включить подклассы, чтобы определить, следует ли реализовать метод доступа к набору для этого свойства. GraphInterface класс определяет метод доступа к набору, вызывающий абстрактный метод (updateGraph, который каждый подкласс должен реализовать). GraphInterface интерфейс накладывает специфическую конструкцию на весь пакет классов, не ограничивая гибкость.

Метод работы со всеми подклассами

addButtons метод добавляет кнопки для zoom методы, которые каждый подкласс должен реализовать. Использование метода вместо обычной функции позволяет addButtons для доступа к защищенным данным класса (дескриптор осей). Использовать объект zoom в качестве обратного вызова по кнопке.

function addButtons(gobj)
   hfig = get(gobj.AxesHandle,'Parent');
   uicontrol(hfig,'Style','pushbutton',...
      'String','Zoom Out',...
      'Callback',@(src,evnt)zoom(gobj,.5));
   uicontrol(hfig,'Style','pushbutton',...
      'String','Zoom In',...
      'Callback',@(src,evnt)zoom(gobj,2),...
      'Position',[100 20 60 20]);
end

Вывести класс бетона - LineGraph

В этом примере определяется только один подкласс, используемый для представления простого линейного графа. Это происходит от GraphInterface, но предоставляет реализации для абстрактных методов draw, zoom, updateGraphи собственный конструктор. Базовый класс GraphInterface и все подклассы содержатся в пакете (graphics), который необходимо использовать для ссылки на имя класса:

classdef LineGraph < graphics.GraphInterface

Добавить свойства

LineGraph реализует интерфейс, определенный в GraphInterface класс и добавляет два дополнительных свойства -LineColor и LineType. Этот класс определяет начальные значения для каждого свойства, поэтому указание значений свойств в конструкторе является необязательным. Можно создать LineGraph без данных, но невозможно создать график из этого объекта.

properties
   LineColor = [0 0 0];
   LineType = '-';
end

Конструктор LineGraph

Конструктор принимает struct с x и y данные координат и пары имя/значение свойства:

function gobj = LineGraph(data,varargin)
   if nargin > 0
      gobj.Data = data;
      if nargin > 2
         for k=1:2:length(varargin)
            gobj.(varargin{k}) = varargin{k+1};
         end
      end
   end
end

Реализация метода розыгрыша

LineGraph draw метод использует значения свойств для создания line объект. LineGraph класс хранит line обрабатывать как защищенные данные класса. Для поддержки использования входных аргументов для конструктора класса, draw проверяет Data чтобы определить, является ли свойство пустым перед продолжением:

function gobj = draw(gobj)
   if isempty(gobj.Data)
      error('The LineGraph object contains no data')
   end
   h = line(gobj.Data.x,gobj.Data.y,...
      'Color',gobj.LineColor,...
      'LineStyle',gobj.LineType);
   gobj.Primitive = h;
   gobj.AxesHandle = get(h,'Parent');
end

Реализация метода масштабирования

LineGraph zoom метод следует за комментариями в GraphInterface класс, который предлагает использовать camzoom функция. camzoom обеспечивает удобный интерфейс для увеличения и корректно работает с кнопками, созданными addButtons способ.

Определение методов набора свойств

Методы набора свойств обеспечивают удобный способ автоматического выполнения кода при первом изменении значения свойства в конструкторе. (См. раздел Методы набора свойств.) linegraph класс использует заданные методы для обновления line примитивные данные (что приводит к перерисовке графика) при каждом изменении значения свойства. Использование методов набора свойств позволяет быстро обновить график данных без вызова draw способ. draw обновляет график, сбрасывая все значения в соответствии с текущими значениями свойств.

Три свойства используют методы набора: LineColor, LineType, и Data. LineColor и LineType являются свойствами, добавленными LineGraph и являются специфическими для line примитив, используемый этим классом. Другие подклассы могут определять различные свойства, уникальные для их специализации (например, FaceColor).

GraphInterface класс реализует Data метод набора свойств. Тем не менее, GraphInterface класс требует, чтобы каждый подкласс определял метод, вызываемый updateGraph, который обрабатывает обновление данных печати для конкретного используемого примитива чертежа.

Класс LineGraph

Вот LineGraph определение класса.

classdef LineGraph < graphics.GraphInterface
   properties
      LineColor = [0 0 0]
      LineType = '-'
   end
   
   methods
      function gobj = LineGraph(data,varargin)
         if nargin > 0
            gobj.Data = data;
            if nargin > 1
               for k=1:2:length(varargin)
                  gobj.(varargin{k}) = varargin{k+1};
               end
            end
         end
      end
      
      function gobj = draw(gobj)
         if isempty(gobj.Data)
            error('The LineGraph object contains no data')
         end
         h = line(gobj.Data.x,gobj.Data.y,...
            'Color',gobj.LineColor,...
            'LineStyle',gobj.LineType);
         gobj.Primitive = h;
         gobj.AxesHandle = h.Parent;
      end
      
      function zoom(gobj,factor)
         camzoom(gobj.AxesHandle,factor)
      end
      
      function updateGraph(gobj)
         set(gobj.Primitive,...
            'XData',gobj.Data.x,...
            'YData',gobj.Data.y)
      end
      
      function set.LineColor(gobj,color)
         gobj.LineColor = color;
         set(gobj.Primitive,'Color',color)
      end
      
      function set.LineType(gobj,ls)
         gobj.LineType = ls;
         set(gobj.Primitive,'LineStyle',ls)
      end
   end
end

Используйте LineGraph Класс

LineGraph класс определяет простой API, указанный graph базовый класс и реализует его специализированный тип графа:

d.x = 1:10;
d.y = rand(10,1);
lg = graphics.LineGraph(d,'LineColor','b','LineType',':');
lg.draw;
lg.addButtons;

При нажатии кнопки «Увеличить» отображается zoom способ обеспечивает обратный вызов для кнопки.

Изменение свойств обновляет график:

d.y = rand(10,1); 
lg.Data = d;
lg.LineColor = [0.9,0.1,0.6]; 

Теперь нажмите «Уменьшить» и просмотрите новые результаты:

Связанные темы