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

Интерфейсы

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

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

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

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

Интерфейсный класс, реализующий графики

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

The 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 

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

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

The 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

Добавление свойств

The 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

Реализуйте метод рисования

The LineGraph draw метод использует значения свойств, чтобы создать line объект. The 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

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

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

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

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

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

The 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 Класс

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

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

Нажатие кнопки Zoom In показывает zoom способ обеспечения коллбэка для кнопки.

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

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

Теперь нажмите Zoom Out и посмотрите новые результаты:

Похожие темы