Свойства и методы, заданные классом, формируют интерфейс, который определяет, как пользователи класса взаимодействуют с объектами класса. При создании группы связанных классов интерфейсы задают общий интерфейс ко всем этим классам. Фактическая реализация интерфейса может отличаться от одного класса до другого.
Считайте набор классов разработанным, чтобы представлять различные типы графиков. Все классы должны реализовать свойство Data
содержать данные, используемые, чтобы сгенерировать график. Однако форма данных может значительно отличаться от одного типа графика другому. Каждый класс может реализовать свойство Data
по-другому.
Те же различия применяются к методам. Все классы могут иметь метод draw
, который создает график, но реализацию этого метода изменения с типом графика.
Основная идея об интерфейсном классе состоит в том, чтобы задать свойства и методы, которые каждый подкласс должен реализовать, не задавая фактическую реализацию. Этот подход позволяет вам осуществить сопоставимый интерфейс группе связанных объектов. Когда вы добавляете больше классов в будущем, интерфейс остается то же самое.
Этот пример создает интерфейс для классов, используемых, чтобы представлять специализированные графики. Интерфейс является абстрактным классом, который задает свойства и методы, которые подклассы должны реализовать, но не задают, как реализовать эти компоненты.
Этот подход осуществляет использование сопоставимого интерфейса при обеспечении необходимой гибкости, чтобы реализовать внутренние работы каждого специализированного подкласса по-другому.
В этом примере папка пакета содержит интерфейс, выведенные подклассы и служебную функцию:
+graphics/GraphInterface.m % abstract interface class +graphics/LineGraph.m % concrete subclass
Класс 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
Этот пример задает только один подкласс, используемый, чтобы представлять простой линейный график. Это выводит от GraphInterface
, но обеспечивает реализации для абстрактных методов draw
, zoom
, updateGraph
и его собственный конструктор. GraphInterface
базового класса и подкласс все содержатся в пакете (graphics
), который необходимо использовать, чтобы сослаться на имя класса:
classdef LineGraph < graphics.GraphInterface
Класс LineGraph
реализует интерфейс, заданный в классе GraphInterface
, и добавляет два дополнительных свойства — LineColor
и LineType
. Этот класс задает начальные значения для каждого свойства, так определение, что значения свойств в конструкторе являются дополнительными. Можно создать объект LineGraph
без данных, но вы не можете произвести график из того объекта.
properties LineColor = [0 0 0]; LineType = '-'; end
Конструктор принимает 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
.
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 и смотрите новые результаты: