Свойства и методы, определенные классом, образуют интерфейс, определяющий взаимодействие пользователей класса с объектами класса. При создании группы связанных классов интерфейсы определяют общий интерфейс для всех этих классов. Фактические реализации интерфейса могут отличаться от одного класса к другому.
Рассмотрим набор классов, предназначенных для представления различных типов графов. Все классы должны реализовывать 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
В этом примере определяется только один подкласс, используемый для представления простого линейного графа. Это происходит от 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
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 определение класса.
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];
Теперь нажмите «Уменьшить» и просмотрите новые результаты:
