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

Интерфейсы

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

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

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

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

Интерфейсные графики реализации класса

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

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

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

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

Interface Properties и методы

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

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

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

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

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

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

  • draw — Используемый, чтобы создать примитивный рисунок и представить график данных согласно типу графика, реализованного подклассом.

  • изменение масштаба Реализация метода изменения масштаба путем изменения свойства 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

Реализация Метода ничьей

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

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

Метод zoom LineGraph следует комментариям в классе 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 In показывает метод zoom, обеспечивающий коллбэк для кнопки.

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

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

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

Похожие темы