
Министерство образования и науки Российской Федерации
Рязанский государственный радиотехнический университет
В.Ф. ОДИНОКОВ
MATLAB R2008a. КЛАССЫ
Часть 2
Учебное пособие
Рязань 2011
УДК 519.68 (075.8)
MATLABR2008a. Классы. Часть 2: учеб. пособие / В.Ф. Одиноков; Рязан. гос. радиотехн. ун-т. - Рязань, 2011. - 80 с.
Рассматриваются основные понятия и элементы MATLAB-классов версии 7.6.0 (R2008a).
Предназначено для студентов специальностей 230201 - "Информационные системы и технологии", 230203 – "Информационные технологии в дизайне", 230204 – "Информационные технологии в медиаиндустрии", бакалавров направления 230200 – "Информационные системы", студентов заочной формы обучения, в том числе по специальности 230201, магистрантов и аспирантов.
Табл. 2. Библиогр.: 3 назв.
В создании пособия принимала участие студентка гр. 735 Степанова Н.В.
Классы, подклассы, объекты, методы
Печатается по решению редакционно-издательского совета Рязанского государственного радиотехнического университета.
Рецензент: кафедра автоматизированных систем управления Рязанского государственного радиотехнического университета (зав. кафедрой д-р техн. наук, проф. Г.И. Нечаев)
Рязанский государственный
радиотехнический университет, 2011
Введение
Без моделирования различных объектов и протекающих в них процессов невозможны почти никакие серьезные исследования и разработки ни в одной из областей знаний. Повышению производительности труда при этом способствуют разнообразные (готовые) системы программной имитации. Одной из таких систем является универсальный пакет МATLAB 7.6.0 (R2008а), включающий ряд функциональных элементов. Все они представлены соответствующими разделами в путеводителеHelpNavigatorпакета МATLAB. Среди них важнейшим является раздел МATLAB(Матричная лаборатория). Он содержит язык, методологию и средства программирования. Программирование в системе МATLAB основано на объектно-ориентированной технологии. Последняя изложена в подразделеMATLAB Classes and Object-Oriented Programming(MATLAB-классы и объектно-ориентированное программирование) разделаМATLAB.
Отсутствие русифицированного варианта пакета МATLAB создает значительные трудности при практической работе с ним. Различная литература [1, 2] по системе МATLAB на русском языке только отчасти решает отмеченную проблему, поскольку преследует, в основном, учебные цели. В отличие от этого данное пособие ориентировано на непосредственноеобщение с МATLAB-документами, так как является продолжением [3] синхронного (в порядке дерева тем путеводителяHelpNavigator) перевода-изложения вышеуказанного подраздела системы МATLAB.
ЭлектронныйHelp-справочник пакета
МATLAB, имея цветовое оформление и
автоматические ссылки на соответствующие
страницы собственной документации, не
может быть полностью воспроизведен в
черно-белом варианте бумажного носителя
данного пособия. Поэтому следует
отметить ряд формальных моментов. Так,
смысловое ударение на слова и фразы в
тексте пособия показанонаклоннымшрифтом. Цветовое выделение всехзаголовков, функций и ключевых словокнаHelpв пособии замененожирнымшрифтом.Графическиецветовые элементы пакета МATLAB в данном
материале различаются только оттенками
серого тона. Всё выделенное жирным
шрифтом иподчеркнутоев пособии
означаетавтоматический вызоввHelpсоответствующих страниц
пакета при однократном нажатии (клике)
левой кнопкой мыши таких ссылок-связей.Специальновыделяемые в тексте
пособия элементы окружены символами
«». Расстановка абзацев и табуляцияподчиняются, в основном, правилам
окнаHelp. Шрифт обычного
текста пособия -TimesNewRoman, программный код -Courier
New,
названия разделов и подразделов -Arial
Black. Знаки «%»послестрок
программного кода означают начало или
продолжение неисполняемого текста –
комментария; наличие или отсутствие
ограничителя «;» в конце строккодаопределяется синтаксисомязыкаMATLAB; многоточие «…» без
разрядки (шрифтTimesNewRoman) означает «и т.д.»,
«проч.», «и др.»; многоточие «...»
с разрядкой (шрифтCourier
New)
– перенос продолжения строки кода.
Понятия «раздел» и «подраздел» условны:
любойподразделкак отдельный
тематический элементHelp-навигатора
является обобщающим разделомдля
своих внутренних структурных составляющих.
Example — Representing Structured Data (Пример - представление структурированных данных)
В этом разделе: |
Display Fully Commented Example Code(Отображение полностью комментированного примера кода);
Objects As Data Structures (Объекты как структуры данных);
Structure of the Data (Структура данных);
Defining the TensileData Class (Определение класса TensileData);
Creating an Instance and Assigning Data (Создание инстанции и назначение данных);
Restricting Properties to Specific Values (Ограничение свойств специальными значениями);
Simplifying the Interface with a Constructor (Упрощение интерфейса с конструктором);
Dependent Properties (Зависимые свойства);
Displaying TensileData Objects (Отображение TensileData-объектов);
A Method to Plot Stress vs. Strain (Метод построения графика stress относительно strain). |
Display Fully Commented Example Code(Отображение полностью комментированного примера кода)
Open class code in a popup window(Открыть код класса в выпадающем окне) – используйте эту связь, если вы хотите наблюдать конечный код для рассматриваемого класса.
Open class definition file in the MATLAB editor(Открыть файл определения класса в редактореMATLAB) — используйте эту связь, если вы хотите сохранить и модифицировать версию класса.
Чтобы использовать класс, создайте директорию-папку @TensileDataи сохраните файлTensileData.mв ней. Данная папка должна иметь родительскую директорию, которая должна быть наMATLAB-пути.
Objects As Data Structures(Объекты как структуры данных)
Этот пример определяет класс для хранения данных с особой структурой. Использование постоянной структуры для хранения данных делает проще создание функций, которые обрабатывают данные. В то время как обычная MATLAB-структура с поименованными полями, описывающими частные элементы данных, является полезным путем организации данных, использование классов для определения хранилищ данных (свойств) и операций, которые вы выполняете над этими данными, позволяет вам получить преимущества, иллюстрируемые этим примером.
Concepts on Which This Example Is Based(Концепты, на которых базируется этот пример)
Целью данного примера является представление напряженных измерений давление/деформация (stress/strain), которые используются для расчета коэффициента эластичности (Modulus) различных материалов. Простыми словами давление есть усилие, приложенное к материалу, а деформация – результат давления. Их отношение определяет характеристику материала. Хотя это упрощенный процесс, он удобен для примера.
Structure of the Data (Структура данных)
Следующая таблица описывает структуру данных (представлены как имена соответствующих свойств):
Данные |
Описание |
Material (Материал) |
Строка символов, идентифицирующая испытываемый материал
|
SampleNumber (Номер образца)
|
Номер испытуемого образца |
Stress(Давление) |
Вектор чисел, представляющих усилия, прикладываемые к образцу при испытании
|
Strain(Деформация) |
Вектор чисел, представляющих изменение формы образца при определенных величинах давления
|
Modulus (Коэффициент) |
Величина, характеризующая эластичность материала при испытании, вычисленная из данных давление/деформация
|
Defining the TensileData Class (Определение класса TensileData)
Этот класс предназначен для хранения данных, поэтому он определяет свойство для каждого элемента данных. Ниже дан блок класса, определяющий пять свойств и специфицирующий их начальные величины в соответствии с типом данных, которые будут храниться в каждом из свойств. Определение начальных величин не является обязательным, но может быть полезным, если величина свойства не назначается при создании конкретного объекта.
Заметьте, что этот пример начинается с очень простого определения класса и основывается на нем для иллюстрации того, как свойства повышают полезность класса.
classdef TensileData% Начало определения класса %TensileData.
properties % Начало определения свойств.
Material = '';% Имя первого свойства со значением
% «пустая строка»
SampleNumber = 0;% Имя второго свойства со
% значением 0.
Stress% Имя третьего свойства со значением по
% умолчанию (пусто).
Strain % Имя четвертого свойства со значением по
% умолчанию (пусто).
Modulus = 0;% Имя пятого свойства со значением 0.
end
end
Creating an Instance and Assigning Data (Создание инстанции и назначение данных)
Ниже показаны примеры операторов для создания инстанции (TensileData-объекта) класса TensileData, использующего предыдущееclassdef-определение (не содержащегоконструктораобъекта), и назначения величин её свойствам:
td = TensileData;% Создание инстанции (TensileData-объекта
% td) дляпредыдущего classdef-определения (у него нет
% явного конструктора TensileData-объектов, поэтому для такого
% classdef-определения данная командаTensileDataне может
% иметь аргументов).
td.Material = 'Carbon Steel'; % Назначение величины
% Carbon Steel свойству Material объекта td.
td.SampleNumber = 001;% Назначение величины001свойству
%SampleNumberобъектаtd.
td.Stress = [2e4 4e4 6e4 8e4];% Назначение вектора
% давлений (stress)свойствуStressобъектаtd.
td.Strain = [.12 .20 .31 .40];% Назначение вектора
% деформаций (strain)свойствуStrainобъектаtd.
td.Modulus = mean(td.Stress./td.Strain); % Назначение
% средней величины (mean) всех частных отношенийstressи
% strainобъектаtdсвойствуModulus.
Advantages of a Class vs. a Structure Array(Преимущества класса по сравнению со структурным массивом)
Вы можете представить TensileData-объект (tdв вышеприведенных формулировках) как любой структурныйMATLAB-массив. Однако определение структуры данныхкак классимеет следующие преимущества.
Пользователи не могут случайно ошибиться в имени поля без получения сообщения об ошибке. Например, при наборе
>>td.Modulis = … % Ошибка в имениModulus.
в случае обычной MATLAB-структурыtdк ней будет простоавтоматически добавленоновое поле, так как вtdимеется полеModulus, но неModulis. Если жеtdестьинстанция классаTensileDataиспециальногоразрешения на добавление новых свойств нет, будет получено сообщение об ошибке.
Класс проще повторно использовать. Как только вы определили класс, вы можете просто расширить его подклассом, который добавитновые свойства.
Класс проще в идентификации. Класс имеет имя, так что вы можете узнать имена егообъектов с помощью стандартных функцийwhosиclassи браузера рабочей области (Workspace browser). Имя класса делает его удобным для ссылок к записям со значимым именем.
Класс может проверить на правильность величины индивидуальных полей при назначении.
Класс может ограничить доступ к полям, например, позволяя читать поля, но не изменять их.
Следующий раздел описывает, как добавить контроль типов и как ограничить доступ к свойствам в классе TensileData.
Restricting Properties to Specific Values(Ограничение свойств специальными значениями)
Вы можете ограничить значения, которые могут принимать свойства, посредством определения set-метода свойства. ПрограммаMATLABвызывает эту функцию-метод всякий раз, когда задается величина свойства.
Defining the Material Property Set Function (Определение set-функции свойства Material)
Рассматриваемый ниже set-метод ограничивает установку свойстваMaterial одним из возможных вариантов:aluminum(алюминий),stainless steel(нержавеющая сталь) илиcarbon steel(углеродистая сталь).
Добавьте определение этой функции-метода (set.Material) в блокеmethodsвнутри предыдущегоclassdef-кода:
classdef TensileData
properties
Material = 'aluminum'; % Пример задания конкретного
% начального значения свойстваMaterialдля случая
% отсутствия других вариантов установки.
SampleNumber = 0;
Stress
Strain
Modulus = 0;
end % properties
methods
function obj = set.Material(obj,material) % Set-
% метод, вызываемый автоматически прилюбых
% установках (назначениях) свойств. Далее идет проверка
% материала на запрещенные варианты:
if ~(strcmpi(material,'aluminum') ||...
strcmpi(material,'stainless steel') ||...
strcmpi(material,'carbon steel'))
error('Material must be aluminum,... stainless steel, or carbon steel')
%error– встроенная функция вывода сообщения при
% наличии запрещенного варианта материала.
end
% Если материал разрешенный, то:
obj.Material = material;
end % set.Material
end %methods
end %classdef
Когда делается любая попытка установки свойстваMaterialдля конкретного испытуемого образца (obj),MATLAB-программа посылает этот объектobjи специфицируемую величинуmaterialметодуset.Material. Как видно из прокомментированного кода, если принятая величина не совпадает с разрешенными значениями (операторif), выдается сообщение (аргумент стандартной функции error) об ошибке. При отсутствии ошибки специфицируемая величинаmaterialиспользуется дляновойустановки свойства (obj.Material =
= material).
Пример:
>>td = TensileData;% СозданиеTensileData-объекта для
% предыдущего classdef-определения.
>>td.Material = 'composite';% Задание недопустимой
% величины свойству Material. Выдается сообщение:
??? Error using ==> (Ошибка -) TensileData.TensileData>Material_set__ (см. set-метод для свойстваMaterialобъекта классаTensileData)
Material must be aluminum, stainless steel, or carbon steel(Материал должен быть алюминием, нержавеющей или углеродистой сталью)
Simplifying the Interface with a Constructor (Упрощение интерфейса с конструктором)
Вы можете упростить интерфейс для предыдущего класса TensileDataдобавлениемкclassdef-определению (например, в уже имеющийся блокmethods) специальной функции-конструктора, которая:
Позволяет вам посылать данные как аргументы конструктору,
Назначает величины свойствам.
Конструктор является функцией-методом, имеющим имя самого класса:
function td = TensileData(material,samplenum,... stress,strain)% Начало определения
% конструктора с входными аргументами-данными.
if nargin > 0 % Проверка наличия входных аргументов
% у метода TensileData. Если аргументы есть, то:
td.Material = material; % Установка свойства Material
% из входных данных.
td.SampleNumber = samplenum;% Установка свойства
% SampleNumber.
td.Stress = stress; % Установка свойства Stress.
td.Strain = strain;% Установка свойства Strain.
% Если аргументов нет, объект будет создан, но установка
% его свойств в данном конструкторе отменяется.
end %if
end %TensileData
В отличие от ранее приведенного варианта определения класса (без явного конструктора объектов) теперь вы можете создавать TensileData-объект сконкретнымиданными, например:
td = TensileData('carbon steel',1,[2e4 4e4 6e4... 8e4],[.12 .20 .31 .40]);% Здесь даются: материал,
% номер образца и массивы дляstressиstrain.
Calculating Modulus(РасчетModulus)
Заметьте, что функция-конструктор не имеет аргумента для величины (modulus) свойстваModulus. Это потому, что величина дляModulus:
Рассчитывается из данных для свойств StressиStrain;
Изменяется, если меняются значения в StressиStrain.
Следовательно, расчет для Modulusлучше проводить, если величинаmodulusбудетзапрошена. Вы можете осуществить это с помощьюget-метода, который описан в следующем разделе.
Dependent Properties(Зависимые свойства)
TensileData-объектне хранитвеличину свойстваModulus- она рассчитывается тогда, когдазапрашивается. Этот прием позволяет обновлять свойства StressиStrainв любое время, так как до запроса величиныmodulusони не влияют на коэффициентModulus.
Defining the Modulus Property Get Function (Определение get-функции свойства Modulus)
Свойство Modulusзависит отStressиStrain. Данную характеристику (поведение свойстваModulus) отображает специальный параметр - атрибутDependent, который устанавливается вtrue(истина). Это можно сделать в дополнительном блокеpropertiesв составеclassdef-определения.Get-метод для обращения к свойствуModulusсформулируйте в отдельном блокеmethodsтого же определения класса:
properties (Dependent = true)% Все свойства в этом блоке
% properties- зависимые.
Modulus % Свойство с величиной «пусто» по умолчанию.
end
methods
function modulus = get.Modulus(obj)%Get-метод % свойстваModulusобъектаobj, вызываемый прилюбой
% попытке запроса величины этогосвойства.
ind = find(obj.Strain > 0);% Поиск индексов элементов
% массива strainдля ненулевых значений элементов.
modulus = mean(obj.Stress(ind)./... obj.Strain(ind)); % Расчет мodulus.
end %get-метод.
end %methods
Функция-метод get.Modulusпросто рассчитывает среднее (mean) отношение синхронных парstress/strainпосле исключения нулей в знаменателе. Полученная величинаmodulusв виде выходного параметра функции-методаget.Modulusвозвращается в команду-запрос по свойствуModulus.
MATLAB-программа всегда вызывает методget.Modulusпри запросе значения этого свойства. Например:
td = TensileData('carbon steel',1,[2e4 4e4 6e4... 8e4],[.12 .20 .31 .40]); % Создание TensileData-
% объекта для последнего варианта определения класса.
td.Modulus % Обращение кModulus, что приводит к вызову
% метода get.Modulus. Так как аргументDependentэтого
% свойства есть true, оно оказывается зависимым (в свойстве
% Modulusне хранится его значение). В методеget.Modulus
% производится расчет modulus. Так как ограничителя «;» после
% команды обращения нет, следует вывод на экран:
ans = % СтандартнаяMATLAB-переменная.
1.9005e+005 % Значение запрашиваемого свойстваModulus.
Displaying TensileData Objects (Отображение TensileData-объектов)
Класс TensileDataисполняетdisp-метод (переопределенная встроенная функцияdisp), который контролирует, что отображается на экране при наличии соответствующего оператора.
Рассматриваемый ниже пример disp-метода для классаTensileDataотображает результирующие величины свойствMaterial,SampleNumberиModulus. Он не показывает свойстваStressиStrain, поскольку они содержат большие массивы и являются только исходными данными. Более удобный способ отображения данных вStressиStrainв виде графика даетplot-метод (переопределенная стандартная функцияplot), изложенный в следующем разделе.
Данный disp-метод использует стандартную функциюfprintf(см. её описание) форматирования строк отображаемого текста:
methods
function disp(td)
fprintf(1,'Material: %s\nSample ...
Number: %g\nModulus: %1.5g\n',...
td.Material,td.SampleNumber,td.Modulus);
end % disp
end % methods
A Method to Plot Stress vs. Strain (Метод построения графика stress относительно strain)
Полезно отобразить поведение испытуемого образца в виде графика зависимости между stressи strain. Объект классаTensileDataсодержит эти данные, поэтому можно сформулировать (определить) метод класса, который предназначается для построения указанного графика.
Plot-метод классаTensileDataсоздает линию зависимостиstressотносительноstrain(встроенная функцияplot) и добавляет заголовок графика «Stress/Strain plot for Sample» и названия осей (с помощью стандартной функцииtitle) «Strain %» и "Stress (psi)» для стандартизации изображения:
function plot(td,varargin)
plot(td.Strain,td.Stress,varargin{:})
title(['Stress/Strain plot for Sample',...
num2str(td.SampleNumber)])
ylabel('Stress (psi)')
xlabel('Strain %')
end% plot
Имена plot-метода класса (plotв первой строке фрагмента) и обычной встроенной функцииplot(вторая строка) не конфликтуют, так какMATLAB-программа их различает. Поскольку данные для построения графика содержит объект td, имя этого объекта присутствует вplot-методе как первый аргумент.
Второй аргумент varargin(стандартая переменная – список аргументов функций)plot-метода может содержать параметры для линии графика и другие требования, поэтому он передается в стандартную функциюplot; данные эта функция принимает из свойствStrainиStressобъектаtd.
Для примера два оператора:
td = TensileData('carbon steel',1,[2e4 4e4 6e4... 8e4],[.12 .20 .31 .40]); % Вызов конструктора
% TensileData-объекта с указанием значений его
% свойств.
plot(td,'-+g','LineWidth',2)% Обращение кplot-методу
% класса (после tdидут данные для спискаvarargin).
строят нижеследующий график, где:
Stress/StrainplotforSamplt1 – Графикstress/strainдля Образца 1.
Example — Implementing Linked Lists(Пример – исполнение связных списков)
В этом разделе: |
Important Concepts Demonstrated (Демонстрация важных концептов);
dlnode Class Design (Создание класса dlnode);
Creating Doubly Linked Lists (Создание двусвязных списков);
Why a Handle Class for Doubly Linked Lists? (Почемуhandle-класс для двусвязных списков?);
Defining the dlnode Class (Определение класса dlnode);
Specializing the dlnode Class (Специализация класса dlnode);
Displaying Fully Commented Example Code(Отображение полностью комментированного примера кода). |
Displaying Fully Commented Example Code(Отображение полностью комментированного примера кода)
Open class code in a popup window(Открыть код класса в выпадающем окне) – используйте эту связь для просмотра кода этого класса, снабженного ссылками на описательные разделы.
Open class definition file in the MATLAB editor(Открыть файл определения класса вMATLAB-редакторе) – используйте эту связь, если вы хотите сохранить и модифицировать версию класса.
Для использования класса создайте директорию @dlnodeи сохраните файлdlnode.mв ней. Родительская директория для@dlnode должна быть наMATLAB-пути. Или сохраните файлdlnode.mв обычной директории пути (не в @-папке).
Important Concepts Demonstrated (Демонстрация важных концептов)
Encapsulation(Инкапсуляция)
Этот пример показывает, как классы могут инкапсулировать внутреннюю структуру, используемую для выполнения задачи создания двусвязного списка. Инкапсуляция скрываетвнутренние работы класса от другого кода и обеспечивает постоянный интерфейс для программ (клиентов), которые используют этот класс. Он также предотвращает воздействие клиентов на класс, поскольку только методы класса имеют доступ к его определенным данным.
Методы класса определяют операции, которые могут выполняться над представителями (узлами-элементами списка) этого класса. Эти методы скрывают потенциально конфликтный процесс ввода и уничтожения узлов списка в одно и то же время, а именно:
Создание узла посредством посылки класс-конструктору необходимых данных;
Ввод узлов с учетом других узлов в списке (до или после некоторого узла);
Уничтожение узлов в списке.
Смотрите Defining the dlnode Class(Определение классаdlnode) для детализации.
Handle Class Behavior (Поведение handle-классов)
Этот пример показывает применение handle-класса и объясняет, почему он является лучшим выбором для класса. Смотрите Why a Handle Class for Doubly Linked Lists? (Почему handle-класс для двусвязных списков?)
dlnode Class Design (Создание класса dlnode)
Этот пример определяет класс для создания узлов двусвязных списков, в которых каждый узел содержит:
Массив данных;
Связь с последующим узлом;
Связь с предыдущим узлом.
Каждый узел имеет методы, которые позволяют узлу:
Освободиться от связей в списке;
Подсоединиться к предыдущему узлу в списке;
Соединиться с последующим узлом в списке.
Class Properties(Свойства класса)
Каждый узел выполнен как handle-объект (объектhandle-класса) с тремя свойствами:
Data– содержит данные (data)для этого узла;
Next– содержит метку (handle-имя) последующего узла (node) в списке (аргументSetAccessэтого свойства есть private);
Prev– содержитhandle-имя предыдущего узла списка (аргументSetAccessэтого свойства также установлен вprivate).
Следующая диаграмма показывает три node-объекта:n1,n2, и n3:
Class Methods(Методы класса)
Класс dlnodeисполняет следующие методы:
dlnode– конструирует узел и назначает величину dataдля его свойстваData;
insertAfter– вводит узел после рассматриваемого узла;
insertBefore– вводит узел до рассматриваемого узла;
disconnect– убирает узел из списка;
disp– переопределяет стандартную функциюdispтак, чтобы только свойствоDataотображалось на командной линии;
delete– переопределяет встроенную функциюdelete- убирает узел из спискапрежде, чем он будет уничтожен в программе.
Creating Doubly Linked Lists (Создание двусвязных списков)
Вы создаете узел, посылая данные dataдля узла конструктору классаdlnode. Например, следующие простые операторы создают три узла с числами 1, 2, 3 в качестве узловых информационных данныхdata, устанавливаемых далее в свойствахData:
n1=dlnode(1);% Вызовdlnode-конструктора с аргументом 1.
n2=dlnode(2);% Вызовdlnode-конструктора с аргументом 2.
n3=dlnode(3);% Вызовdlnode-конструктора с аргументом 3.
Вы создаете из этих узлов двусвязный список, используя соответствующие методы класса:
n2.insertAfter(n1)% Узел n2 после узла n1.
n3.insertAfter(n2) % Узел n3 после узла n2.
Теперь три узла связаны. Метод disp(см. коды определений) класса отображает данные для любого указанного узла:
n1.Next % Указатель-запрос на узелn2. Ответ:
ans =
Doubly-linked list node with data (Узел двусвязного списка с данными):
2
n2.Next.Prev % Указатель-запрос на узелn2. Ответ:
ans =
Doubly-linked list node with data (Узел двусвязного списка с данными):
2
n1.Next.Next % Указатель-запрос на узелn3. Ответ:
ans =
Doubly-linked list node with data (Узел двусвязного списка с данными):
3
n3.Prev.Prev % Указатель-запрос на узелn1. Ответ:
ans =
Doubly-linked list node with data (Узел двусвязного списка с данными):
1
Why a Handle Class for Doubly Linked Lists? (Почемуhandle-класс для двусвязных списков?)
Каждый узел уникален в том, что никакие два узла не могут быть предыдущими или последующими для того же самого узла. Предположим, что dlnode-объект содержит в своем свойствеNextметку последующегоdlnode-объекта (узла), а свойствоPrevсодержит метку предыдущего узла.
Используя связный список, определенный в предыдущем разделе, вы можете убедиться, что следующие выражения являются верными:
n1.Next == n2
n2.Prev == n1
Теперь допустим, что вы обозначили n2как х:
x = n2;
Тогда верны следующие два равенства:
x == n1.Next
x.Prev == n1
Но любая инстанция-узел уникальна, так что есть только один узел в списке, который может быть равным n1.Nextи имеет свойствоPrev, содержащее меткуn1. Следовательно,xдолжен указывать в приведенных выражениях на тот же самый узел n2. Это означает, что и другие переменные, введенные вместоx, должны указывать на ту же самую инстанцию.Только handle-классобеспечивает одно значение дляx иn2, соответствующее одному и тому же узлу. Другие инстанцииhandle-класса используют такой же образец поведения.
Напомним, что handle-класс определяет методeq(равенство), который предусматривает использование знака «==» со всемиhandle-объектами.
Смотрите раздел Comparing Handle and Value Classes(Сравнениеhandle- иvalue-классов) для информации о свойствахMATLAB-классов.
Смотрите раздел The Handle Base Class(Базовый классhandle) с дополнительными данными поhandle-классам.
Defining the dlnode Class (Определение класса dlnode)
Пусть следующий двусвязный список использован в данном примере:
n1=dlnode(1);
n2=dlnode(2);
n3=dlnode(3);
n2.insertAfter(n1)
n3.insertAfter(n2)
Class Properties(Свойства класса)
Класс dlnodeявляетсяhandle-классом, потому что он выведен из абстрактного классаhandle. Заметьте, что свойстваNextиPrevмогут быть установлены только посредством методов класса (их аргументSetAccess = private) для предотвращения нежелательных операций над свойствами со стороны клиент-кодов:
classdef dlnode < handle
properties % Свойства доступны извнепо умолчанию.
Data
end
properties (SetAccess = private) % Свойства
% доступны только классу (его объект-инстанциям).
Next
Prev
end
end
Creating a Node Object (Создание node-объекта)
Для создания node-объекта (dlnode-объекта) вам необходимо специфицировать только его данныеdata. Поэтому функция-конструктор будет иметь только один аргумент:
function node = dlnode(data)
if nargin > 0% Проверка наличия аргументов. Если да, то:
node.Data = data;% Установка свойстваData(при
% этом автоматическивызываетсяset-метод данного
% свойства).
end
end
Disconnecting Nodes (Отсоединение узлов)
Метод отсоединения удаляет узел из списка и создает (восстанавливает) другой список путем соединения оставшихся узлов. Для этого вначале вызывается удаляемый узел, запоминается текущее состояние его свойств NextиPrev, а потом производится восстановление списка и обнуление свойств удаляемого узла (окончательное удаление):
function disconnect(node)% Функция-метод отсоединения
% удаляемого узла nodeи последующего восстановления
% образовавшегося разорванного списка.
Prev = node.Prev;% Обращение к свойствуPrevобъекта
% node(например,n2) для запоминания его состояния (в
% данном случае метка n1) левой переменнойPrev; значение
% свойства node.Prevявляется узлом, предыдущим для
% данного node, поэтому левая переменная Prevстановится
% тоже узлом-объектом.
Next = node.Next;% Обращение к свойствуNextобъекта
% nodeи запоминание его значения (в нашем случае метка
% n3); левая переменнаяNext, как и значение свойства
% node.Next, становится узлом-объектом.
if ~isempty(Prev)% Проверка действительного значения
% переменной Prev (пустой объект не имеет свойств).
Prev.Next = Next;% Установка свойстваNextобъекта-
% переменной Prev(присоединение объектаPrev
% (здесь n1) к объекту-переменнойNext(здесь n3)).
end
if ~isempty(Next)% Проверка действительного значения
% переменной Next.
Next.Prev = Prev;% Установка свойстваPrevобъекта
% Next- присоединение объектаNext(здесьn3) к
% объекту Prev(здесь n1).
% Установкой свойств узлов PrevиNextзаканчивается
% восстановление связного списка – теперь узел n1соединен с
% n3.
end
node.Next = []; % Обнуление свойстваNextобъектаnode.
node.Prev = []; % Обнуление свойстваPrevобъектаnode.
% Сбросом исходных значений (связей) свойств узла node
% завершается его полное удаление из связного списка.
end
Трансформацию (восстановление) связного списка для конкретного примера можно представить обычным текстом, если использовать значения свойств PrevиNextизымаемого объектаn2предыдущего трехузлового списка:
n1 = n2.Prev;
n3 = n2.Next;
ifn1exists,then(еслиn1 существует, то):
n1.Next = n3;
if n3 exists, then (если n3 существует, то):
n3.Prev = n1
Inserting Nodes (Вставление узлов)
Вставляемый узел может иметь связи с другими узлами списка. Поэтому сначала необходимо его отсоединить (метод disconnect– см. коды определения). Для последующего вставления этого узла в другое место списка используем два метода –insertAfter(вставление после) иinsertBefore(вставление до). Эти методы выполняют похожие операции, поэтому детально опишем толькоinsertAfter:
methods
function insertAfter(newNode, nodeBefore) % Метод
% введения нового узлаnewNodeпосле узла
% nodeBefore.
disconnect(newNode); % Отсоединение узла newNode
% от других узлов списка и восстановление (создание
% нового) списка.
newNode.Next = nodeBefore.Next;% Установка
% значения (пустого после операции disconnect)
% свойства Nextнового узлаnewNode в виде узлаNext, к
% которому ранее был присоединен узел nodeBefore.
newNode.Prev = nodeBefore;% Установка пустого
% свойства PrevузлаnewNodeв виде узла
% nodeBefore.
if ~isempty(nodeBefore.Next) % Проверка
% действительного значения свойстваNextузла
% nodeBefore.
nodeBefore.Next.Prev = newNode;% Установка
% свойства PrevузлаnodeBefore.Next.
end
nodeBefore.Next = newNode;% Установка свойства
% NextузлаnodeBefore.
end
end
Для примера вставим ранее удаленный узел n2после узлаn1, соединенного пока сn3:
n2.insertAfter(n1)% Первый аргументnewNodeметода
% insertAfterбудет взят из самой команды (узелn2).
Процесс изменения связей в списке можно записать текстом так:
n2.Next=n1.Next; %n1.Nextявляется узломn3 (связьn1-n3);
% производится установка значения n2.Next(новая связь
% n2 -n3).
n2.Prev=n1; % В качестве предыдущего дляn2 заказан узелn1,
% устанавливается связь n1 -n2.
ifn1.Nextisnotempty,then(еслиn1.Nextне пусто, то):
n1.Next.Prev=n2; %n1.Nextявляется узломn3, предыдущим
% (Next.Prev) дляn3 является узелn1; это обстоятельство
% нужно изменить – предыдущим для n3 устанавливается
% узел n2.
n1.Next=n2; %n1.Nextесть узелn3; устанавливается новое
% значение для n1.Next(связьn1 -n2).
Displaying a Node on the Command Line (Отображение узла на командной линии)
Объекты любых классов, при необходимости, вызывают по умолчанию стандартную функцию disp, которая отображает все свойства объектов и их величины на командной линии. Для рассматриваемого случая это не интересно, поскольку свойстваNextиPrevузлов-объектов просто содержат другие узлы. Следовательно, классdlnodeдолжен переопределить стандартную функциюdispдля отображения, например, какого-либо текста сообщения и значения свойствData:
function disp(node)% Метод, переопределяющий стандартную % функциюdisp, используемую объектомnode.
disp('Doubly-linked list node with data:')
%disp- стандартная функция отображения текста:
% «Узел двусвязного списка с данными:».
disp(node.Data);% Стандартная функцияdispдля
% отображения величины свойства Dataузлаnode.
end
Deleting a Node Object (Уничтожение node-объекта)
Когда вы определили для handle-классаdelete-метод, он, при необходимости, вызывается до того, как объект будет уничтожен. Объектыdlnodeявляются узлами связного списка, поэтому важно сначала отсоединить узел до его уничтожения. Другими словами, до полного уничтожения объекта связи с ним должны быть разорваны. Функция-методdisconnectвdelete-методе выполняет эти действия:
function delete(node)% Метод, переопределяющий
% стандартную функцию deleteприменительно кhandle-классу
% dlnode.
disconnect(node); % Вызов для узла node метода disconnect,
% разрывающего имеющиеся связи с узлом, восстанавливающего
% далее связный список (с образованием нового списка) и
% уничтожающего все указания на бывшие связи узла node
% (теперь узел не задействован в списке).
end
Specializing the dlnode Class (Специализация класса dlnode)
Класс dlnodeисполняет двусвязный список и является удобной стартовой точкой для создания более специализированных типов связных списков. Например, допустим, что вы хотите создать список, в котором каждый узел имеет светское имя (кроме метки илиhandle-идентификатора).
Вместо того чтобы копировать старый код для dlnodeи затем модернизировать его под новые задачи, вы можете вывести новый класс изdlnode(dlnode-подкласс), который имеет все характеристики класса dlnodeс добавлением новых свойств. Посколькуdlnodeявляетсяhandle-классом, выведенный подкласс (например,NamedNode) будет такжеhandle-классом.
Следующее определение показывает, как выводится подкласс NamedNodeиз класса dlnode:
classdef NamedNode < dlnode % Заимствование в новом классе
% (dlnode-подклассе)NamedNode всех функций и свойств класса
% dlnode.
properties
Name = '';% Дополнение (только для класса NamedNode) к
% dlnode-свойствам нового (пока пустого) свойства.
end
methods
function n = NamedNode (name,data) % Конструктор
% объекта (сhandle-идентификаторомn) класса
% NamedNode; задаетname(светское имя) и данные data
% соответственно для свойств NameиData.
if nargin == 0% Если аргументы конструктора
% отсутствуют, то все значения свойств объекта n,
% которые должны быть установлены, следует обнулить
% (их не передали в конструктор):
name = '';
data = [];
end
n = n@dlnode(data);% Сигнатура вызова конструктора
% суперкласса dlnodeдля установки в объектеn
% данных data, так как в определении классаNamedNode
% нет свойства Data.
n.Name = name;% Передача аргументаnameв объектn.
end
function disp(n)% Переопределение стандартной функции
% dispпод новые цели (здесь двукратное использование
% этой функции):
disp(['Node Name: ' n.Name])% Отображение
% светского имени узла n(из его свойстваName)
% после слов «Node Name:» (Имя узла:).
disp(['Node Data: ' num2str(n.Data)]) % Отобра-
% жение (после слов «Node Data:») данных из
% свойства n.Dataпутем их преобразования (стандартная % функцияnum2str) в символьную строку.
end
end %methods
end% classdef
Как видим, класс NamedNodeдобавляет (к унаследованным отdlnode) свойствоNameдля хранения светского имени узла и переопределяет стандартный метод disp. Конструктор классаNamedNodeвызывает конструктор суперклассаdlnodeдля установки свойстваDataи затем устанавливает (назначает) свойствоName.
Отметим, что конструктор NamedNodeзапланирован и для случая отсутствия аргументовnameи data. В последнем случае имя и данные обнуляются, что учитывается в последующих операторах. СмотритеBasic Structure of Constructor Methods(Базовая структура конструктор-методов) для более подробной информации о методах-конструкторах.
Using the NamedNode Class to Create a Doubly Linked List (Использование класса NamedNode для создания двусвязного списка)
Используйте класс NamedNodeспособом, аналогичным для прежнего класса dlnode. Например:
n1=NamedNode('First Node',100);
n2=NamedNode('Second Node',200);
n3=NamedNode('Third Node',300);
Здесь первые аргументы вызовов – светские имена узлов, вторые – данные data. Далее используйте методы вставления узлов, наследованные от суперкласса dlnodeдля построения спискаNamedNode-объектов:
n2.insertAfter(n1)
n3.insertAfter(n2)
Узлы отображают свои имена и данные, когда свойства запрашиваются:
>> n1.Next% Запрос. Ответ:
ans =
Node Name: Second Node (Второй узел)
Node Data: 200
>> n1.Next.Next % Запрос. Ответ:
ans =
Node Name: Third Node (Третий узел)
Node Data: 300
>> n3.Prev.Prev % Запрос. Ответ:
ans =
Node Name: First Node (Первый узел)
Node Data: 100
Example — Class for Graphing Functions (Пример - класс для графических функций)
В этом разделе: |
Display Fully Commented Example Code (Отображение полностью комментированного примера кода);
Class Definition Block(Блок определения класса);
Using the topo Class (Использование класса topo);
Behavior of the Handle Class (Поведение handle-класса). |
Как обычно, блок класса начинается с ключа classdefи заканчивается словомend. Следующий пример иллюстрирует простое определение класса, который использует:
Handle-класс;
Set- иget-функции для свойств;
Delete-метод дляhandle-объектов;
Синтаксис для статического метода.
Display Fully Commented Example Code(Отображение полностью комментированного примера кода)
Вы можете отобразить это определение класса в выделенном окне, которое связано с разделами документации, если щелкнуть заголовок:
Example with links (Пример со связями)
Class Definition Block(Блок определения класса)
Следующий код определяет класс, названный topoи предназначенный для построения трехмерного графика с координатамиx,y,z, из которыхzрассчитывается по даннымx,y. Классtopoвыведен из суперклассаhandle, поэтому сам являетсяhandle-классом, что означает ссылкина данныев нем. СмотритеUsing the topo Class(Использование классаtopo) для информации о поведении этого класса.
classdef topo < handle % topo – подкласс суперкласса handle.
properties % Первый блок следующих свойств:
FigHandle = []; % Это свойство содержитhandle-имя фигуры
% (ссылка для её копий осуществляется на исходные данные);
% назначение для этого свойства делается только при создании
% конкретного topo-объекта, здесьFigHandle можно не
% задавать как [] (известно по умолчанию).
FofXY% Это свойство (пока пустое по умолчанию) хранитhandle-
% функцию (задаетtopo-объект) двух аргументов (x,y), по
% которым вычисляется координата z.
Lm = [-2*pi 2*pi];% Возможные пределы вариации xиy.
end % properties
properties (Dependent = true) % Значения свойств этого
% блока не хранятся, так как они зависимые, т.е. вычисляются
% при запросе.
Data % Свойство данного блокаproperties.
end % properties (Dependent = true)
methods
function obj = topo(fnc,limits) % Конструктор topo-
% объекта;fnc–handle-функция (не имеет собственного
% файла определения) двух аргументов; limits– пределы
% изменения аргументов функции fnc.
obj.FofXY = fnc;% ПередачаfncвFofXY.
obj.Lm = limits; % Передача limits в Lm.
end % topo
function lm = set.Lm(obj,lim) % Set-метод установки
% свойстваLmобъектаobj по данным массиваlim.
if ~(lim(1) < lim(2))% Проверка соотношения
% пределов в двухэлементном массиве lim.
error('Limits must be monotonically... increasing')% Вывод сообщения: «Пределы
% должны быть монотонно возрастающими».
else % Если пределы правильные, то:
obj.Lm = lim;% УстановкаLmпоlim.
end
end % set.Lm
function data = get.Data(obj) % Get-метод для свойства
% Data объекта obj.
[x,y] = topo.grid(obj.Lm); % Указывайте имя класса
% (здесьtopo)для статического метода(здесьgrid-
% получение массивов аргументов xиy).
matrix = obj.FofXY(x,y);% Вычисление ординатz
% функцией fnc(вFofXY) по аргументамx,y.
data.X = x;% Копированиеx; так как имяdata не было
% заявлено как объект какого-либо класса, MATLAB
% воспринимает data.Xкак указание на поле Xобычной
% структуры dataсвойстваData(т.е.obj.Data.X).
data.Y = y;% Копированиеyв полеYструктурыdata
% (обращение к data.Y-obj.Data.Y).
data.Matrix = matrix;% Копированиеz(можно без
% matrix, а именно: data.Matrix =
% =obj.FofXY(x,y)) в полеMatrixструктурыdata
% (обращение к data.Matrix-obj.Data.Matrix).
end % get.Data
function surflight(obj) % Метод-функция построения
% графика для obj.
surf(obj.Data.X,obj.Data.Y,...
obj.Data.Matrix,'FaceColor',...
[.8 .8 0],'EdgeColor',[0 .2 0],...
'FaceLighting','phong');% Стандарт-
% ная функция surfпостроения графика
% поверхность/контур по результатам метода get.Data
% объекта objи параметрам цвет/освещение.
% Дополнительные заказы на параметры графика:
camlight left;% Заказ на подсветку.
material shiny;% Заказ на отражение.
grid off% Стандартная команда устранения сетки (не
% путать со статическим методом grid).
colormap copper % Заказ на особый цвет.
obj.FigHandle = gcf;% Объявление величины в
% FigHandleтекущей (на данный момент) фигурой.
end % surflight.
function delete(obj) % Переопределение стандартной
% функцииdeleteдля новых целей:
h = obj.FigHandle;% Передача значения изFigHandle
% переменной h.
if ishandle(h)% Стандартная проверкаhна типHandle
% Graphics(графическийhandle-объект).
delete(h); % Вызов стандартной функцииdeleteдля
% уничтожения h.
else
return % Возврат в точку вызова при невыполнении
% условия ishandle(h).
end
end % delete
end % methods
methods (Static = true) % Определение статического метода.
function [x,y] = grid(lim) % Функция-метод
% формирования массивов аргументов x,y в пределах lim.
inc = (lim(2)-lim(1))/35;% Расчет инкремента (шага).
[x,y] = meshgrid(lim(1):inc:lim(2)); % Вычисле -
% ние массивовx,y.
end%grid
end % methods (Static = true)
end % topo-класс
Using the topo Class(Использование классаtopo)
Этот класс предназначен для построения и отображения комбинированного графика поверхность/контур математических функций двух переменных прямоугольной области xиy. Например, любая из следующих функций может быть оценена в заданной области (отметим, что в этом примере xи yимеют одни и те же границы только для простоты):
x.*exp(-x.^2 - y.^2); [-2 2]% Функцияx.*exp(-x.^2 -
% - y.^2)и пределы[-2 2]вариации аргументовxиy.
sin(x).*sin(y); [-2*pi 2*pi] % Функция sin(x).*sin(y)
% и пределы[-2*pi 2*pi]вариации аргументовxиy.
sqrt(x.^2 + y.^2); [-2*pi 2*pi]% Функцияsqrt(x.^2 +
% + y.^2)и пределы[-2*pi 2*pi]вариацииxиy.
Для создания инстанции класса пошлите handle-функциюfncи векторlimitsпределов к конструктору класса. Простейшим путем созданияhandle-функции является использование анонимной функции, например:
tobj = topo(@(x,y) x.*exp(-x.^2-y.^2),[-2 2]);%topo– вызов класс-конструктора с передачей ему анонимной
% handle-функции@(x,y) x.*exp(-x.^2-y.^2)(не имеющей
% собственного файла определения) и пределов изменения аргументов
% xиy(от «-2» до «+2»).
Метод surflight(см. выше) использует объект для создания графика функции. Нужные данные для построения графика не хранятся, но когда методsurflightобращается к свойствуData, это автоматически ведет к вызову функции-методаget.Data,которая производит расчет значений всех полей структурыdata(цель расчета – ординатаz), используемых для графика.
Behavior of the Handle Class (Поведение handle-класса)
Класс topoопределен какhandle-класс. Это значит, что инстанции этого класса являютсяhandle-объектами, которые используют основное хранилище (контейнер) данных, созданное при конструировании объекта. Например, пусть вы создаете инстанциюtobjклассаtopoи копиюa этого объекта:
tobj = topo(@(x,y) x.*exp(-x.^2-y.^2),[-2 2]);
% Здесьtopo– вызов конструктора объекта tobj.
a = tobj; % a - копия topo-объекта tobj.
surflight(a)% Вызов метода классаtopoдля создания графика:
Теперь допустим, что вы меняете FofXYтак, что оно содержит другую анонимнуюhandle-функцию:
tobj.FofXY = @(x,y) y.*exp(-x.^2-y.^2);% Теперь
% функция expумножается не на x, а наy.
surflight(a)% Снова строим график дляa:
Поскольку a–handle-копия (не автономная переменная) объектаtobj, изменение значения свойстваFofXYобъектаtobjменяет данные и для его копии, что очевидно из сравнения двух фигур.
How a Value Class Differs (Чем отличается value-класс)
Если бы topoбылvalue-классом, объектыtobjиане разделяли бы одни и те же данные - каждый имел бы свою собственную (автономную) копию значений свойств.
Working with Classes(Работа с классами)
Перечень тем раздела и их краткие характеристики.
Class Overview(Обзор классов) Что такоеMATLAB-классы
Defining Classes — SyntaxСинтаксис класса и простой
(Определение классов – синтаксис) пример
Class Attributes(Атрибуты класса) Описание атрибутов, которые
модифицируют поведение класса
Перечень тем раздела и их краткие характеристики (продолжение).
Organizing Classes in Directories Директории для определений
(Организация классов в директориях) классов
Specifying Class PrecedenceУстановка относительного (Спецификация класс- предпочтение средиuser-defined-
предпочтения) классов
Scoping Classes with PackagesЧто такое пакеты и как получить (Ограничение сферы классов доступ к их содержанию
пакетами)
Saving and Loading ObjectsРабота с объектами в процессе (Сохранение и загрузка объектов) сохранения и загрузки
Importing ClassesИмпорт классов в функции для (Импорт классов) упрощения именных ссылок
Defining Named ConstantsИспользование класса с (Определение именованных постоянными свойствами для констант) определения постоянных величин
Obtaining Information AboutMeta-классы обеспечиваютClasses with Meta-Classesинспектирование классов (Получение информации о классах программным путем
с помощью meta-классов)
Class Overview(Обзор классов)
В этом разделе: |
MATLAB User-Defined Classes (MATLAB-user-defined-классы).
|
MATLAB User-Defined Classes ( MATLAB-user-defined-классы)
User-defined-классы, в отличие от собственных классов пакетаMATLAB, требуют определения классов и их компонентов – методов, свойств и событий силамиMATLAB-пользователей. Определение класса и его компонентов имеет целью описание элементов, общих для всех инстанций класса.
MATLAB-user-defined-классы должны быть определены в блокеclassdef с внутренними субблоками определений различных компонентов класса. Смотритеclassdef Syntax(classdef-синтаксис) для детализации элементовclassdef-определения.
Attributes for Class Members (Атрибуты компонентов класса)
Атрибуты модифицируют поведение классов и компонентов, определенных в блоке classdef. Например, вы можете задать, что методы являются статическими или что свойства являются абстрактными и т.д. Следующие разделы описывает эти атрибуты:
Class Attributes(Атрибуты класса);
Method Attributes(Атрибуты методов);
Specifying Property Attributes(Спецификация атрибутов свойств);
Event Attributes(Атрибуты событий).
Класс может предоставить информацию такую, как наследование отношений или имена компонентов класса, без конструирования класса. Смотрите Obtaining Information About Classes with Meta-Classes(Получение информации о классах с помощьюmeta-классов).
Смотрите Specifying Attributes(Спецификация атрибутов) о синтаксисе атрибутов.
Kinds of Classes (Типы классов)
Есть два типа MATLAB-классов –handle- иvalue-классы. Они различаются по принципу организации и ссылок на данные:
Handle-классы создают объекты, которые ссылаются на содержащиеся в классах данные. Копии объектов используют те же самые данные;
Value-классы делают свои копии данных при любом копировании объекта или посылки в функцию. ЧисловыеMATLAB-типы данных являютсяvalue-классами.
Смотрите Comparing Handle and Value Classes(Сравнениеhandle- иvalue-классов) для более подробной информации.
Creating Class Hierarchies (Создание иерархий классов)
Для получения информации о том, как понимать и создавать иерархию классов, смотрите Building on Other Classes(Конструирование из других классов).
Defining Classes — Syntax(Определение классов – синтаксис)
В этом разделе: |
classdef Syntax(classdef-синтаксис)
|
classdef Syntax(classdef-синтаксис)
Определение класса является блоком кода, который начинается с ключевого слова classdefи заканчивается словомend. Файлы могут включать толькопо одному определению класса.
Следующая диаграмма показывает синтаксис блока classdef. Только комментарии и пустые строки могут предшествовать ключевому словуclassdef.
Ключевое слово
classdef
начинает определение
Ключевое слово
end
заканчивает
определение
Атрибут класса
Величина атрибута
(логическое «истина»)
Имя класса
Супер-классы
Блок
classdef
Examples of Class Definitions (Примеры определений класса)
Смотрите следующие примеры класс-определений:
Example — Representing Structured Data(Пример – представление структурированных данных);
Example — Implementing Linked Lists(Пример – исполнение связных списков);
Developing Classes — Typical Workflow(Создание классов – типовой рабочий процесс);
Example — A Polynomial Class (Пример – класс полиномов).
Class Attributes(Атрибуты класса)
В этом разделе: |
Table of Class Attributes (Таблица атрибутов класса);
Specifying Attributes (Спецификация атрибутов).
|
Table of Class Attributes (Таблица атрибутов класса)
Все классы поддерживают атрибуты, представленные в следующей таблице. Атрибуты позволяют вам модифицировать поведение класса. Величины (если не по умолчанию) атрибутов добавляют к определению класса в блоке classdef.
Таблица атрибутов класса
Имя атрибута |
Класс |
Описание |
Hidden |
logical (по умолчанию = = false) |
Если установлен в true, класс не появляется на выходеMATLAB-команды или средства, отображающего имя класса
|
InferiorClasses |
cell (по умолчанию = = {}) |
Используйте этот атрибут для установки отношения предпочтения среди классов. Специфицируйте массив ячеек объектов meta-классов, используя оператор «?». |
Окончание таблицы
Имя атрибута |
Класс |
Описание |
|
|
Встроенные классы - double, single, char, logical, int64, uint64, int32, uint32, int16, uint16, int8, uint8, cell, struct и function_handle всегда подчинены пользовательским классам и не показаны в данной таблице.
Смотрите Specifying Class Precedence(Спецификация класс-предпочтения)
|
ConstructOnLoad |
logical (по умолчанию = =false) |
Если true, класс-конструктор вызывается автоматически, когда объект загружается изMAT-файла. Следовательно, конструктор должен быть выполнен так, чтобы вызов без аргументов не сопровождался ошибкой.
Смотрите Saving and Loading Objects(Сохранение и загрузка объектов)
|
Sealed |
logical (по умолчанию = =false) |
Если true, из класса нельзя выводить подклассы.
|
Specifying Attributes(Спецификация атрибутов)
В общем, атрибуты (вышеприведенной таблицы и аналогичных таблиц) могут специфицироваться как для самого класса, так и для компонентов класса в блоках classdef, properties, methodsиevents. Значения атрибутов относятся ко всем составляющим конкретного блока. Это означает, что вы должны иметь несколько блоков любого типа для различных спецификаций атрибутов в этих блоках.
Inheritance of Superclass Attributes (Наследование атрибутов суперклассов)
Атрибуты класса не наследуются. Поэтому атрибуты суперклассов не влияют на подклассыза исключениематрибутаInferiorClasses. СмотритеSpecifying Class Precedence(Спецификация класс-предпочтения) для большей информации об этом атрибуте.
Attribute Syntax(Синтаксис атрибутов)
Специфицируйте (если не по умолчанию) значения атрибутов в круглых скобках, отделяя каждую пару «имя атрибута»/«величина атрибута» запятой. Список атрибутов всегда следует за словом classdefили ключевым словом компонентов класса, как показано ниже:
classdef (Attributename = expression, …) ClassName
% Attributename - имя атрибута, expression - выражение,
% задающее величину атрибута;ClassName– имя класса.
properties (Аttributename = expression, …)
…
end
methods (Аttributename = expression, …)
…
end
events (Аttributename = expression, …)
…
end
end
Evaluating Expressions in Attribute Assignments (Оценка выражений в назначениях атрибутов)
Термин expressionв предыдущем блоке использован для обозначения любого легальногоMATLAB-выражения, которое при оценке приводится к одиночному массиву. Выражение оценивается, когда класс впервые используется, и результирующая величина является далее константой.
Язык MATLABоценивает выражение в его собственном контексте ине может ссылаться на переменные или класс, который определяется. Элементы выражениямогутссылаться на статические методы и статические свойства других классов и использоватьMATLAB-путь класса во время оценки. Это значит, что выражение не может иметь доступ к переменным рабочей областиMATLAB, но может иметь доступ к любой функции и статическим методам или свойствам, которые содержатся наMATLAB-пути во время оценки.
Например, в следующем classdef-определении атрибутSealedиспользует стандартную функциюisdir(определяет, действительно ли аргумент-вход есть директория) и будет установлен в логическую единицу (true), если директорияmyDirнаходится наMATLAB-пути (т.е. доступна):
classdef (Sealed = isdir('myDir'))
Organizing Classes in Directories (Организация классов в директориях)
В этом разделе: |
Options for Class Directory (Опции для класс-директории);
@-Directories(@-директории);
Path Directories(Директории пути);
Class Precedence and MATLAB Path (Класс-предпочтение и MATLAB-путь).
|
Options for Class Directory (Опции для класс-директории)
Имеются два типа директорий, которые могут содержать определения классов. Они отличаются своим расположением на MATLAB-пути:
@-директория (@-папка) – имя такой директории начинается с @ и не находится на MATLAB-пути, но её родительская директория должна находиться наMATLAB-пути. Несколько @-папок могут иметь одну и ту же родительскую директорию. Используйте этот тип директории, когда вы хотите определить класс по частям несколькими файлами. При этом может быть толькоодинкласс в каждой @-папке и имя класса должно совпадать с именем @-директории без символа @.
Директория пути – имя директории не использует символ @ и само находится на MATLAB-пути. При этом определение любого класса сосредоточено в одном единственном файле (не может содержать отдельные файлы разных частей класса).
Смотрите функцию pathдля информации оMATLAB-пути.
@-Directories(@-директории)
@-директория расположена на какой-либо директории пути, но сама не является путем. Вы помещаете файл classdef-определения класса внутри @-папки, которая можетдополнительносодержать файлы методов класса,выделенныхизclassdef-определения. Файлclassdef-определения класса должен иметь то же имя, что и @-директория (без знака @), иclassdef-линия должна появляться на файле раньше другого кода (комментарии и пустые строки не относятся к коду). Имя класса должно соответствовать имени файла, который содержитclassdef-определение класса.
Вы должны использовать @-директории, если хотите иметь более одного файла для класса (файл classdef-определения и файлы методов). Имена файлов методов и имена самих функций-методов должны совпадать.
Path Directories(Директории пути)
Вы можете разместить определения классов в директориях, которые находятся на MATLAB-пути. Эти классы представлены на пути подобно обычным функциям. Определения классов, расположенные на таких директориях, ведут себя аналогично обычным функциям с учетом предпочтений –первоеимя наMATLAB-пути предпочтительнейвсех остальных.
Имя файла на такой директории должно соответствовать имени класса, как специфицировано в classdef-определении. Использование директории пути устраняет необходимость создания выделенной @-директории для класса. Однако все части класса должны содержаться целикомвнутри одногофайла (внутриclassdef-определения).
Class Precedence and MATLAB Path (Класс-предпочтение и MATLAB-путь)
Когда имеется много файлов с теми же самыми именами, предпочтение конкретного файла зависит от его размещения на MATLAB-пути. Все файлы определения классов, расположенные раньше на пути (независимо от того, есть знак @ или нет), предпочтительней остальных.
Для примера рассмотрим путь со следующими директориями:
dir1/foo.m% определяет классfoo.
dir2/foo.m% определяет функциюfoo.
dir3/@foo/foo.m% определяет классfoo.
dir4/@foo/bar.m% определяет методbarклассаfoo.
dir5/foo.m% определяет классfoo.
Язык MATLABиспользует следующую логику вызоваfoo:
Класс dir1/foo.m(и любая функция по отношению к директории без знака @) предпочтительнее любых следующих классов и функций, поскольку он раньше появляется на пути.
Класс dir3/@fooпредпочтительнее функцииdir2/foo.m, так как @-директории классовпредпочтительнейдиректорий функций.
Функция dir2/foo.mпредпочтительней классаdir5/foo.mпо первому правилу доступа.
Класс dir3/@fooпредпочтительнейdir4/@foo, поскольку первым расположен на пути; следовательно, к методуbar.mкласса@fooнетдоступа (bar.mдолжен быть вdir3/@foo).
Если dir3/@foo/foo.mне содержит ключевого словаclassdef(т.е. является классом до версии 7.6), то dir4/@foo/bar.mстановится методом классаfoo, определенного вdir3/@foo.
Previous Behavior of Classes Defined in @-Directories(Прежнее поведение классов, определенных в @-директориях)
В версиях MATLABс 5 по 7 одни @-директории не отличались от других @-директорий, имеющих те же имена в разных частях пути. Вместо этого класс определялся комбинацией методов всех @-директорий, имеющих те же имена. Такое положение в последующих версияхне являетсяверным.
Specifying Class Precedence(Спецификация класс-предпочтения)
В этом разделе: |
InferiorClasses Attribute (Атрибут InferiorClasses).
|
InferiorClasses Attribute(АтрибутInferiorClasses)
Вы можете задать относительное предпочтение классов, используя атрибут InferiorClasses. Назначьте массив ячеек (в фигурных скобках) имен классов, представленных какmeta.class-объекты (объекты, поставляющие информацию о классах), этому атрибуту для указания действительных классов, которые подчинены определяемому вами классу. Например, следующийclassdefобъявляет, чтоmyClassявляется старшим надclass1иclass2:
classdef (InferiorClasses = ...
{?class1,?class2}) myClass
…
end
Оператор «?» в сочетании с именем класса создаетmeta.class-объект. Этот синтаксис позволяет создать такой объект без конструктора инстанции указанного в операторе«?» действительного класса.
Встроенные MATLAB-классывсегда подчиненыклассам, определеннымMATLAB-пользователями (user-defined-классы), и не упоминаются в рассматриваемом списке подчинения.
Встроенные классы: double, single, char, logical, int64, uint64, int32, uint32, int16, uint16, int8, uint8, cell, struct и function_handle.
More Information(Дополнительная информация)
Смотрите Determining Which Method Is Invoked(Определение, какой метод следует привлечь) для изучения, как действуютMATLAB-классы при оценке выражений, содержащих объекты.
Смотрите Class Precedence(Класс-предпочтение) иMATLAB Path (MATLAB-путь) для получения сведений о том, как размещение наMATLAB-пути определения класса влияет на его предпочтение.
Смотрите Obtaining Information About Classes with Meta-Classes(Получение информации о классах с помощьюmeta-классов) для ознакомления с объектамиmeta-классов.
Inheriting Inferior Classes(Наследование подчинения классов)
Подчинение классов, специфицированное атрибутом InferiorClasses,наследуетсяподклассами. Если подкласс также определяет свой атрибутInferiorClasses, его истинный список подчиненных классов есть объединение подчиненных классов данного подкласса и всех классов унаследованного подчинения.
Scoping Classes with Packages(Ограничение сферы классов пакетами)
В этом разделе: |
Package Directory(Пакетная директория);
Referencing Package Members from Outside the Package (Ссылка на компоненты пакета извне пакета;
Packages and MATLAB Path (Пакеты и MATLAB-путь).
|
Package Directory(Пакетная директория)
Пакеты являются специальными директориями, которые могут содержать директории классов, функций и другие пакеты. Пакеты определяют сферу (иногда называемую сферой имен) для пакетной директории. Это значит, что имена функций и классов должны быть уникальными только внутри пакета. Использование пакета изолирует имена этих компонентов, которые могут быть повторноиспользованы в других директориях.
Заметка. Пакеты не поддерживаются дляMATLAB-классов до версии 7.6 (т.е. классов, которые не используютclassdef). |
+mypack% Пакет директорий.
+mypack/pkfunc.m% Пакетная функция.
+mypack/@myClass% Класс в пакете.
Сами пакеты не могут являться самостоятельным элементомMATLAB-пути, но их родительские директории должны быть на этом пути.
Referencing Package Members Within Packages (Ссылка на компоненты пакета внутри пакетов)
Все ссылки внутри пакета на пакеты, функции и классы должны использовать префикс пакетного имени, если это не импортированный в рабочую область пакет (см. Importing Classes- Импорт классов). Поэтому вызывайте функцию, напримерpkfcnпакета mypack, следующим образом:
z = mypack.pkfcn(x,y);
Следует отметить, что сами определения не используютпакетный префикс. Так, следующая строка определения функцииpkfcnвключает только имя функции:
function z = pkfcn(x,y)
Аналогично определяется пакетный класс, например:
classdef myClass
Однако вызов этого класса, как и функции pkfcn, требует имя пакета, например:
obj = mypack.myClass(arg1,arg2,…);
После созданияобъекта с указанием пакета, где расположен конструктор класса, последующий вызов, например методов этого класса для объекта, ужене требуетимени пакета. Пример:
obj.myMethod(arg) или
myMethod(obj,arg)
Только статический метод(например,stMethod)требует пакетное имя класса, потому что такой методне связанс созданным объектом:
mypack.myClass.stMethod(arg)
Referencing Package Members from Outside the Package (Ссылка на компоненты пакета извне пакета)
Поскольку функции, классы и другие пакеты, содержащиеся в каком-либо пакете, ограничены этим пакетом, то для ссылки извне на любой компонент пакета вы должны использовать префикс имени пакета для этого компонента, отделенный точкой. Например, следующее выражение создает объект класса myClass, который находится в пакетеmypack:
obj = mypack.myClass;
Accessing Class Members — Various Scenarios(Доступ к компонентам класса – различные сценарии)
Ниже показаны варианты доступа к компонентам пакета извне пакета. Предположим, вы имеете пакет mypackсо следующими директориями:
+mypack
+mypack/myfcn.m
+mypack/@myfirstclass
+mypack/@myfirstclass/myfcn.m
+mypack/@myfirstclass/otherfcn.m
+mypack/@myfirstclass/myfirstclass.m
+mypack/@mysecondclass
+mypack/@mysecondclass/mysecondclass.m
+mypack/+mysubpack
+mypack/+mysubpack/myfcn.m
Вызовите, например, функцию myfcnпакетаmypack:
mypack.myfcn(arg)
Теперь создайте инстанции классов, которые имеют файлы определения (из перечисленных выше такие файлы есть только в шестой и восьмой директории):
obj1 = mypack.myfirstclass;
obj2 = mypack.mysecondclass(arg);
Вызовите функцию myfcn пакета mysubpack:
mypack.mysubpack.myfcn(arg1,arg2);
Если mypack.myfirstclassимеет метод, названныйmyfcn, последний вызывается как любой метод, вызываемый объектом, если этот объект уже определен с указанием соответствующего пакета:
obj = mypack.myfirstclass;% Объектobjопределен.
myfcn(obj,arg);% Вызов методаmyfcnдля уже созданного
% объекта obj.
Если mypack.myfirstclassимеет свойство, называемоеMyProp, оно назначается с использованиемdot-нотации и объекта также без указания пакета, если последний уже определен самим объектом:
obj = mypack.myfirstclass;% Объектobjопределен.
obj.MyProp = some_value;% Назначение величины
% some_valueсвойствуMyProp созданного объектаobj.
Packages and MATLAB Path (Пакеты и MATLAB-путь)
Вы не можетедобавить сами пакетные директории кMATLAB-пути, нодолжныдобавить к нему родительскую директорию пакета. Даже если пакетная директория есть текущая директория, её родительская директория дополнительно должна быть наMATLAB-пути, иначе пакетный компонент не будет доступен.
Все пакетные компоненты (см. примеры пакетных директорий выше) ограничены сферой пакета. Вы должны, таким образом, всегда ссылаться на пакетные компоненты (если это не импортированные пакеты и объектные свойства и методы), используя имя пакета.
Пакетные директории не скрадываютдругие одноименные пакетные директории, которые позиционируются позже на пути, в отличие от классов, которые затеняют другие классы (для них обращение идеттолькок первому из одноименных классов на пути).
Resolving Redundant Names(Решение проблемы избыточных имен)
Допустим, что пакет и класс имеют одно и то же имя (символ «+» только указывает на пакет), например:
dir1/+foo
dir2/@foo/foo.m
Тогда команда which(стандартный запрос по функциям и файлам) дляfoo:
>> which foo
дает очевидный ответ:
dir2/@foo/foo.m
В рассмотренном примере функция и пакет могут иметь одно и то же имя. При этом следует отметить, что само имя пакета не является достаточным идентификатором, поэтому, если избыточное (повторяющееся) имя появляется одно, оно указывает на функцию(не на пакет с тем же именем). Указание же только имени пакета возвращает ошибку.
Package Functions vs. Static Methods(Пакетные функции против статических методов)
В случаях разных директорий, где функции расположены в пакетах и классах, имеющих одно и то же имя, статический метод предпочтительнейпакетной функции, например:
dir1/+foo/bar.m%barесть функция пакетаfoo.
dir2/@foo/bar.m%barесть статический метод класса foo.
Поэтому стандартный запрос which дляfoo.barи ожидаемый ответ следующие:
>> which foo.bar % Запрос.
dir2/@foo/bar.m % Ответ.
В случаях, где одна директория пути содержит пакетные директории и директории классов с одинаковыми именами, статический метод-функция также берет приоритет над пакетными функциями, например:
dir1/@foo/bar.m%barесть статический метод классаfoo.
dir1/+foo/bar.m%barесть функция пакетаfoo.
Запрос whichотносительноfoo.barи реакция на запрос в данной ситуации прежние:
>> which foo.bar % Запрос.
dir1/@foo/bar.m % Ответ.
Saving and Loading Objects(Сохранение и загрузка объектов)
В этом разделе: |
Modifying the Save and Load Process(Модификация процессов сохранения и загрузки);
Code for These Examples(Код для этих примеров);
Processing Objects During Load Operations(Обработка объектов во время операций загрузки);
Processing Objects During Save and Load Operation(Обработка объектов во время операций сохранения и загрузки). |
Modifying the Save and Load Process(Модификация процессов сохранения и загрузки)
Вы можете сохранить (save) объекты вMAT-файлах и затем перезагрузить (load) их в рабочую область памяти. В большинстве случаев сохранение и загрузка объектов изMAT-файлов не отличаются от работы с другими переменными. Однако вы можете изменить процессы сохранения и загрузки в соответствии с ситуацией.
Class saveobj and loadobj Methods (Класс-методы saveobj и loadobj)
Вы можете определить методы для вашего класса, которые выполняются, когда вы сохраняете или загружаете объекты.
Метод saveobjвызывается стандартной функциейsaveраньше исполнения самих операций по сохранению. Функцияsaveзатем сохраняет (отправляет вMAT-файл) величину, возвращенную методомsaveobj. При этом методsaveobjможет модифицировать объект или переменную любого другого типа такую, как структурный массив.
Метод loadobjвызывается стандартной функциейloadраньше выполнения самих операций загрузки. Функцияloadзагружает затем в рабочую область памяти величину (объект), возвращенную методомloadobj. Определение методаloadobjпозволяет легко модифицировать возвращаемый объект.
Если вы исполняете метод saveobj, который модифицирует сохраняемый объект, то вам, вероятно, потребуется выполнить также и методloadobjдля возврата объекта в прежнее состояние, когда он будет перезагружаться. Например, вы можете захотеть сохранить данные объекта в структурном массиве (в самом объекте данные хранятся в свойствах) и реконструировать объект при перезагрузке для возврата его прежних возможностей, измененных методомsaveobj.
What Information Is Saved(Какая информация сохраняется)
При записи объектов в MAT-файлах сохраняются следующие данные:
Имена и величины всех свойств, не маркированных как TransientилиConstant(см.Specifying Property Attributes- Спецификация атрибутов свойств). Однако с целью уменьшения размера файла величины свойств сохраняются, только если они отличаются от заданных по умолчанию в определении класса;
Полное имя класса объекта, включая любой пакетный идентификатор.
Даже если ваш методsaveobjсохраняет только данные объекта в некотором массиве, но не сам объект, имя класса объекта, как было сказано, сохраняется, поэтому функцияload сможет определить, какой (для объекта какого класса) методloadobj следует вызывать.
How Property Data is Loaded(Как загружаются данные свойств)
Если атрибут ConstructOnLoadустановлен какtrue, процесс загрузки вызывает класс-конструктор без аргументов и создает новый объект класса, используя данные, сохраненные из прежнего объекта. Когда загружаются объекты изMAT-файлов, функцияloadделает следующее:
Сначала переназначает начальные величины, которые были сохранены в MAT-файле;
Затем назначает сохраненные величины тем свойствам, чьи значения - не те же самые, что их начальные величины в момент, когда объект сохранялся;
Каждое из этих назначений (начальных величин или сохраненных значений) вызывает set-метод для свойства, если он определен для него в классе.
В set-методе свойства можно задать причину возможной ошибки (например, определение класса могло быть изменено). Когда ошибка встречается при загрузке объекта из файла, программа помещает сохраненные величины в специальнуюMATLAB-структуруstruct(поскольку сам объект напрямую не может быть при этом реконструирован).
При наличии такой ситуации методу loadobjпосылаетсяstructвместо объекта. Методloadobjдолжен использовать величины вstruct, чтобы вызвать класс-конструктор и создатьновыйобъект.
You Must Implement loadobj as a Static Method (Вы должны исполнять loadobj как статический метод)
Вы должны исполнять метод loadobj как статический метод, посколькуloadobjможет быть вызван сstructили другими данными вместо объекта. Методsaveobjисполняется как обычный (не статический) метод, т.е. его вызов требует инстанцию класса.
Code for These Examples(Код для этих примеров)
Дальнейшие рассуждения о сохранении и загрузке объектов относятся к классу BankAccount. Используйте следующую связь для просмотра полного кода этого класса:
Open in editor(Открыть в редакторе)
Processing Objects During Load Operations(Обработка объектов во время операций загрузки)
Когда вы загружаете объект, который был сохранен в MAT-файле, используя функциюload, сначала вызывается методloadobj, если он существует. Исполнение методаloadobjпозволяет вам сделать некоторую обработку объекта до того, как он будет загружен в рабочую область самой функциейload. Это может быть необходимым в таких случаях:
Определение класса получило изменение за время, когда объект хранился, и необходимо модифицировать объект прежде, чем он будет перезагружен;
Метод saveobjмодифицировал объект во время операции сохранения, возможно сохранив для большей эффективности данные в соответствующем массиве (не в свойствах), и методloadobjдолжен реконструировать объект, основываясь на результатахsaveobj.
Updating an Object Property When Loading with loadobj (Обновление свойства объекта, когда загрузка с loadobj)
В следующем примере метод loadobjпроверяет у сохраненного объекта старый номер счета и вызывает специальную функцию-метод для дополнения номера, если необходимо. После обновления свойстваAccountNumberсохраненного объекта методloadobjвозвращает новый объект для дальнейшей загрузки:
methods (Static = true)% Статический метод, поскольку
% вызывается не объектом класса, а функциейload.
function obj = loadobj(a)% Функция-реконструктор
% сохраненной объект-переменной aв объектobj.
accnb = a.AccountNumber;% Передача номера счета
% из сохраненного объекта aв переменнуюaccnb.
if length(num2str(accnb)) < 12 % Проверка
% длины номера объекта a; если длина не полная, то
% вызывается метод updateAccountNumberдля
% модернизации сохраненного номера:
a.AccountNumber = ...
updateAccountNumber(accnb);
end
% Результат работы метода loadobj– новый объектobj:
obj = a;
end
end
В данном случае метод loadobjиспользуется только для обновления старых сохраненных объектов перед непосредственной загрузкой в рабочую область.
Следующий раздел показывает пример, в котором loadobjвыполняет операцию спецификации для воссоздания объекта, основываясь на данных методаsaveobj, полученных при сохранении.
Processing Objects During Save and Load Operations(Обработка объектов во время операций сохранения и загрузки)
Допустим, что вы знаете определение класса, которое, вероятно, изменится со временем, но вы хотите перезагрузить хранимые (например, в соответствии с первым определением класса) данные и создать объекты для наиболее употребляемого (например, последнего) определения. Один из путей для этого – сохранять данные текущего объекта (которые потом будут данными объекта другого определения) не в самом объекте, а в структуре struct, которую затем и использовать для создания объекта с желаемым определением класса.
Для реализации этого способа создайте метод saveobjдля экстрадиции данных, которые вы хотите сохранить, из текущего объекта (например, для первого определения класса) и записи их вstruct, возвращаемую затем методомsaveobjв функциюsave. При создании объекта в желаемом определении (например, последнем) вы, очевидно, должны исполнить методloadobj для изъятия данных из перезагружаемой переменной (в данном случае сохраненные старые данные объекта) и использования этих данных для создания нового объекта (для желаемого определения), который далее непосредственно загружается в рабочую область памяти.
Saving Object Data Only with saveobj(Сохранение данных объекта только посредствомsaveobj)
Последующий пример сохраняет посредством метода saveobjданные из объекта класса BankAccount, имеющего два свойства (AccountNumberиAccountBalance), в структурной переменнойAс полями, соответствующими именам свойств. Далееsaveobjавтоматически возвращает переменнуюAв функциюsaveдля непосредственного сохранения структурыAвMAT-файле:
methods
function A = saveobj(obj)% Метод saveobj передачи
% значений свойств объектаobjпеременнойA; переменная
% Aне объявлена как объект класса, поэтомуMATLAB
% воспринимает её элементы A.AccountNumberи
% A.AccountBalanceкак поля структурыA:
A.AccountNumber = obj.AccountNumber;
A.AccountBalance = obj.AccountBalance;
end
end
Reconstructing Objects with loadobj (Реконструкция объектов с помощью loadobj)
Допустим, что объекты предыдущего класса BankAccountс двумя свойствами были сохранены, как было показано, в структурных переменныхA. Затем к определению класса было добавлено третье свойство. Все ранее сохраненные в структурной переменнойAс двумя полями объекты должны быть переделаны. Для создания правильного объекта вызовите новый (последний) конструктор, используя сохраненные данные, идобавьтелюбые требуемые элементы (здесь величина нового свойства). Поскольку вы вызвали последнюю версию конструктора, будет создана новая версия объекта.
В следующем примере к свойствам AccountNumberиAccountBalanceклассаBankAccountдобавляется новое свойство, названноеAccountStatus(не показано, добавление осуществляется обычным образом; назначение новому свойству величины ведется в конструкторе из его входных аргументов – третьего после значенийAccountNumberиAccountBalance). Если баланс счета (полеAccountBalance в A) больше, чем ноль,AccountStatusустанавливается вopen. Если баланс счета – ноль или меньше,AccountStatusустанавливается вoverdrawn(или, например,frozen).
Указанные проверки величины AccountBalance и определения статусаAccountStatusпроводит методloadobj. Он же и вызывает требуемый класс-конструктор для передачи ему необходимой информации:
methods (Static = true) % Статический метод, поскольку
% вызывается не объектом класса, а функцией load.
function obj = loadobj(A) % Метод loadobj
% предназначен для преобразования переменнойAвобъект
% obj.
if A.AccountBalance > 0% Проверка величины
% баланса.
obj = BankAccount(А.AccountNumber,...
А.AccountBalance,'open'); % Вызов нового
% класс-конструктора с передачей ему сохраненных
% значений старых свойств и величины openдля
% нового свойства AccountStatus.
else% Если баланс не положительный, значение нового
% свойства AccountStatus будет overdrawn:
obj = BankAccount(А.AccountNumber,...
А.AccountBalance,'overdrawn');
end
end
end
saveobj Method Expanded (Расширенный метод saveobj)
Использование saveobjиloadobjдля учета изменений определений классов, вероятно, потребует от вас обновлять эти методы при каждой модификации класса. Но вы можете объединить старые и модифицированные объекты расширенным методомsaveobj(пример сохранения объектов предыдущего классаBankAccountсдвумя или тремясвойствами):
methods
function A = saveobj(obj)% Метод сохранения объекта
% objв виде переменнойA.
A.AccountNumber = obj.AccountNumber; Перенос
% AccountNumber из obj в A (A автоматически
% становится структурой, так как не объявлена
% объектом).
A.AccountBalance = obj.AccountBalance % Пере-
% нос AccountBalance из obj в A.
if isaPropertyOf(obj,'AccountStatus') % Обра-
% щение к методу (см. следующий раздел) класса
% BankAccount. Он проверяет, является ли
% AccountStatusсвойством объектаobj. Если
% это так, то:
A.AccountStatus = obj.AccountStatus;
end
% Если вышеуказанного свойства AccountStatusу
% используемого объекта objнет, то оно далее просто не
% упоминаетсяза ненадобностью.
end % function
end% methods
Does an Object Have a Particular Property (Имеет ли объект конкретное свойство)
Ниже некоторый класс определяет статический метод, который контролирует, есть ли свойство PropNameу загружаемого объекта. Для этого используется упомянутая выше функцияisaPropertyOf. В данном примере она проверяет, есть ли у загружаемого объекта свойствоAccountStatus, передаваемое на место формального параметраPropName(любая строка дляPropNameобрамляется кавычками):
methods (Static = true)% Статический метод, поскольку он
% вызывается не объектом.
function tf = isaPropertyOf(anyobj,PropName)
% Данная функция-метод проверяет, есть ли у объекта
% anyobjсвойство PropName.
if ~isa(anyobj,'meta.class')% Еслиanyobj–
% объект не meta-класса, то таковой надо создать, так
% как толькоmeta-класс предоставит всю нужную
% информацию о свойствах и их количестве в объекте
% anyobj:
mobj = metaclass(anyobj);
else % Еслиanyobj– объектmeta-класса, то:
mobj = anyobj;
end
tf = false;% Назначение результата проверки , пока она не
% проведена.
for k=1:length(mobj.Properties)% Для всех свойств:
if strcmp(mobj.Properties{k}.Name,...
PropName)% если значениеk-го свойства и имени
% PropNameсовпадают, то:
tf = true;
% Переменная tfдалее автоматически возвращается в точку
% вызова метода isaPropertyOf(например, оператор
% ifпредыдущего модуля сохранения -saveobj).
end
end
end % function
end % methods
Заметьте, что вы можете также использовать этот метод для определения, есть ли у класса конкретное свойство, без создания инстанции класса. Например, следующий код проверяет, имеет ли класс BankAccountсвойство, именуемоеAccountType(здесь «?» – конструкторmeta-класса):
isaPropertyOf(?BankAccount,'AccountType')
Аргумент ?BankAccountсоздает объектmeta-класса, который далее используется для проверки наличия уBankAccountсвойстваAccountType.
Смотрите Obtaining Information About Classes with Meta-Classes(Получение информации о классах с помощьюmeta-классов) для дополнительной информации оmeta-классах.
Importing Classes(Импорт классов)
В этом разделе: |
Syntax for Importing Classes(Синтаксис для импорта классов);
Importing Class Member(Импорт компонентов класса). |
Syntax for Importing Classes(Синтаксис для импорта классов)
Вы можете импортировать классы в функцию для облегчения доступак компонентам класса. Для примера рассмотрим пакет pkg, который содержит несколько классов, но вам нужно использовать только один класс в вашей функции. Вы можете использовать, например, следующую команду-модуль (здесь не показано, для чего нужен объект, создаваемый функцией):
function myFunc % Начало модуляmyFunc для создания
% объекта.
import pkg.cls1 % Стандартная команда для импорта
% класса cls1 из пакета pkgв рабочую область % функции myFunc.
obj = cls1(arg,...);% Вызов конструктора классаcls1для
% создания объекта obj(пакет уже не указывается).
end
Вы можете также импортировать все классы в пакете, используя синтаксис pkg.*, где «*» указывает на все классы в пакете. Например:
function myFunc
import pkg.* % Импорт всех классов из пакетаpkg.
obj1 = cls1(arg,...); % Вызов конструктора классаcls1.
obj2 = cls2(arg,...); % Вызов конструктора классаcls2.
end
Importing Class Members (Импорт компонентов класса)
Вы можете импортировать статические методы, постоянные свойства и имена перечислений, определенных в классе. Для импорта компонентов класса используйте в команде import стандартную класс-нотациюclass, например:
import class package.class.* % Импорт всех компонентов
% класса classиз пакетаpackage.
Для примера рассмотрим функцию myFunc, импортирующую все компоненты классаpkg.cls1и постоянное свойствоCиз классаpkg.consts:
function myFunc
import class pkg.cls1.* % Импорт всех компонентов
% класса cls1из пакетаpkg.
import class pkg.consts.C% Импорт постоянного
% свойства Склассаconstsиз пакетаpkg.
obj = cls1(arg,...); % Вызов конструктора классаcls1.
m = calcMass; % Использование статического метода класса
% cls1.
e = m*C^2; % Использование свойстваСклассаconsts.
end
Defining Named Constants (Определение именованных констант)
В этом разделе: |
Creating a Class for Named Constants (Создание класса именованных констант). |
Creating a Class for Named Constants(Создание класса именованных констант)
Существуют ситуации, когда полезно определить коллекцию констант, чьи величины доступны по имени. Чтобы такое обеспечить, создайте класс, имеющий свойства с атрибутом Constant=true. Заметьте, что установка атрибутаConstantвtrueэффективнее при значенииprivateатрибутаSetAccess, так как при этом свойства не могут быть изменены извне класса. Вы можете задать пакет классов, определяющих различные множества констант, и импортировать их в любую функцию.
A Package for Constants (Пакет для констант)
Для создания библиотеки констант сначала создайте пакетную директорию, затем определите различные классы для организации разных констант. Например, чтобы выполнить установку констант, используемых для астрономических расчетов, вы можете определить класс AstroConstantsв пакетеConstants:
+Constants/@AstroConstants/AstroConstants.m
Класс AstroConstantsопределяет свойства (с атрибутомConstant = = true)с назначенными начальными значениями, например:
classdef AstroConstants
properties (Constant = true)
C = 2.99792458e8; % m/s
G = 6.67259; % m/kgs
Me = 5.976e24; % Масса Земли (kg).
Re = 6.378e6; % Радиус Земли (m).
end
end
Для использования этих констант вам следует ссылаться на них с полным именем класса. Например, следующая функция использует некоторые из констант, определенных в AstroConstants:
function E = energyToOrbit(m,r)
… E = Constants.AstroConstants.G *...
Constants.AstroConstants.M * m *...
(1/Constants.AstroConstants.Re – 0.5*r);
end
Obtaining Information About Classes with Meta-Classes (Получение информации о классах с помощью meta-классов)
В этом разделе: |
What Are Meta-Classes (Что такое meta-классы);
Inspecting a Class(Инспектирование класса).
|
What Are Meta-Classes (Что такое meta-классы)
Meta-классы (в общем определении) – это классы, которыесодержат информациюо традиционных (обычных) классах. Каждый блок в обычном определении классауже имеетсвой соответствующийmeta-класс, который содержит информацию об атрибутах этого блока. Каждый обычныйатрибутсоответствует определенномусвойствувmeta-классе.
Meta-классы позволяют программным путем инспектировать все характеристики и элементы классов. Данная техника используется такими средствами, как инспекторы свойств, отладчики и др.
The Meta Package (Meta-пакет)
Meta-пакет (в общем определении) является пакетомmeta-классов, которые определены для традиционных классов и их составляющих. Конкретное имяmeta-класса показывает компонент, описанный им:
meta.package % Meta-класс MATLAB-пакетов.
meta.class % Meta-класс класса.
meta.property % Meta-класс свойств.
meta.method % Meta-класс методов.
meta.event %Meta-класс событий.
Каждый из перечисленных meta-классов вmeta-пакете имеет свойства, методы и события, которые содержат информацию оMATLAB-пакете, обычном классе или его компоненте. Смотритеmeta.package, meta.class, meta.property, meta.methodиmeta. event для более подробных сведений оmeta-классах.
Creating Meta-Class Objects (Создание объектов meta-классов)
Вы можете создавать объекты meta-классов прямо из традиционных классов или их инстанций:
?classname— возвращаетmeta-объект для класса с именемclassname(meta.class-объект);
metaclass(obj)— возвращаетmeta-объект для класс-инстанцииobj(meta.class-объект);
Примеры:
mobj = ?classname;% Созданиеmeta-класс-объектаmobjдля
% класса classname.
obj = myClass;% Получение инстанцииobj для создания его
% meta-класс-объекта.
mobj = metaclass(obj);% Созданиеmeta-класс-объектаmobj
% для инстанции objклассаmyClass.
Заметьте, что встроенная MATLAB-функцияmetaclassвозвращаетmeta.class-объект(т.е. объект класса meta.class). Вы можете получить другиеmeta-объекты (meta.property-объект,meta.method-объект и т.д.) изmeta.class-объекта.
Заметка:Meta-класс – это термин, используемый для описания типа класса; meta.classесть класс, чьи инстанции содержат информацию об обычныхMATLAB-классах. |
Using Meta-Class Objects(Использование объектовmeta-классов)
Объекты meta-классов можно использовать, если они получены следующим путем:
meta-объекты из класс-определений (с помощью «?») или из класс-инстанций (посредством стандартной функцииmetaclass);
meta-объекты свойств, методов и событий.
Ниже примеры показывают эти варианты.
Inspecting a Class(Инспектирование класса)
Рассмотрим следующий класс и информацию, которую вы можете получить с помощью его meta-инстанций. КлассEmployeeDataестьhandle-класс с двумя свойствами, одно из которых определяетсяset-функцией допуска. Способность собирать информацию о классе программным путем без необходимости иметь инстанцию класса может быть полезна, когда используются такие средства, как инспектор, отладчик кода и др.:
classdef EmployeeData < handle
properties
EmployeeName
end
properties (GetAccess = private)
EmployeeNumber
end
methods
function obj = EmployeeData(name,ss)
obj.EmployeeName = name;
obj.EmployeeNumber = ss;
end
function obj = set.EmployeeName(obj,name)
if ischar(name)% Еслиname– строка символов, то:
obj.EmployeeName = name;
else % Иначе вывод сообщения:
error('Employee name must be a ... text string')% «Имя
% служащего должно быть текстом».
end
end
end
end
Inspecting the Class Definition (Инспектирование класс-определения)
Используя определенный выше (исходный) класс EmployeeData, можно создать для негоmeta.class-объект с помощью оператора «?»:
mboj = ?EmployeeData;
Теперь вы можете определить, откуда выведен класс EmployeeData:
a = mobj.SuperClasses;% Передача информациив ячейки
% массива a о суперклассах класса EmployeeData.
a{1}.Name % Запрос на имя суперкласса (первая ячейка массива a)
% класса EmployeeData. Ответ:
ans =
handle
Inspecting Properties (Инспектирование свойств). Предположим, вы хотите знать имена свойств, определенных в исходном классе. Сначала получите массивmeta.properties-объектов, соответствующих исходным свойствам класса, из свойстваPropertiesобъекта класса meta.class:
mpCell = mobj.Properties;% Массив свойств (meta-объектов
% для свойств исходного класса EmployeeData)meta.class-
% объекта (mpCell- массив ячеек).
Длина lengthмассиваmpCellпоказывает, что имеются дваmeta.property-объекта, по одному на каждое исходное свойство:
length(mpCell)% Запрос на длину массиваmpCell. Ответ:
ans =
2
Теперь выделим meta.property-объект из первой ячейки массиваmpCell:
prop1 = mpCell{1} % Выделение объекта из первой ячейки
% массива mpCell; так как ограничителя «;» нет, сразу следует
% отображение результата:
prop1 =
meta.property % prop1-объект класса meta.property.
prop1.Name% Запрос на свойствоNamemeta-объекта в ячейке
% mpCell{1}. Ответ:
ans =
EmployeeName% Имя соответствующего исходного свойства
% класса EmployeeData.
Можно запросить любое из свойств meta.property-объектов для класса EmployeeData. Некоторые ответы представляются в виде специальных handle-директорий (признак – «@»), например:
setmeth = prop1.SetMethod % Запрос на свойство
% SetMethod meta-объекта prop1. Ответ:
setmeth =
@D:\MyDir\@EmployeeData\EmployeeData.m>...
EmployeeData.set.EmployeeName % Handle-
% директория кset-методу для свойства
% EmployeeName, расположенному в класс-файле
% EmployeeData.mпапки@EmployeeData(MATLAB
% выводит директорию непрерывной строкой, здесь вывод
% разделен на две части из-за ограниченной ширины листа).
Inspecting an Instance of a Class (Инспектирование инстанции класса)
Рассмотрим создание объекта класса EmployeeDataи его инспектирование:
EdObj = EmployeeData('My Name',1234567);% Создание
% исходного объекта классаEmployeeData.
mEdObj = metaclass(EdObj);% Создание meta.class-объекта.
mpCell = mEdobj.Properties; % Выделение свойства
% Properties meta-объекта mEdObj.
eval(['EdObj.',mpCell{1}.Name]) % Оценка конкатенации
% (объединения) имениEdObjи ответа (EmployeeName)на
% запрос о свойстве Nameпервогоmeta-объекта массива mpCell:
ans =
My Name % My Name возвращено функцией eval из
%EdObj.EmployeeName(результат предыдущей
% конкатенации) – значение свойства EmployeeNameисходного
% объекта EdObj.
eval(['EdObj.',mpCell{2}.Name]) % То же, что и выше для
% второго объекта массива mpCell. Результат оценки:
??? Getting the 'EmployeeNumber' property of the 'EmployeeData' class is not allowed (??? Получение
значения свойства EmployeeNumberкласса
EmployeeDataне разрешено) % Данное сообщение легко
% проверить:
mpCell{2}.GetAccess % Запрос на свойствоGetAccessmeta-
% объекта mpCell{2} - допуск к исходному свойству:
ans =
private
Value or Handle Class — Which to Use (Value- или handle-класс – что использовать)
Разделы по этой теме и их краткие характеристики.
Comparing Handle and Value Когда использовать handle- и
Classes(Сравнениеvalue- и когда использоватьvalue-классы.
handle-классов)
Which Kind of Class to UseИнформация о том, какой тип класса
(Какой тип класса использовать) использовать.
The Handle Base Class Методы класса handle.
(Базовый класс handle)
Finding Handle Objects and Использование findobj и
Properties(Поискhandle-объектов findprop
и свойств)
Implementing a Set/Get Interface Создание удобного интерфейса для
for Properties(Исполнение вашегоhandle-класса.
set/get-интерфейса для свойств)
Comparing Handle and Value Classes (Сравнение value- и handle-классов)
В этом разделе: |
Why Select Value or Handle (Почему выбирается value или handle);
Behavior of MATLAB Built-In Classes (Поведение встроенных MATLAB-классов);
Behavior of User-Defined Classes (Поведение user-defined-классов). |
Why Select Value or Handle (Почему выбирается value или handle)
MATLABподдерживает два типа классов –value-классы (классы величин) иhandle-классы (классы меток -handle-имен). Выбор типа класса зависит от желаемого поведения инстанций класса. Например, нужны ли вам события и слушатели, динамические свойства и т.д.
Раздел Which Kind of Class to Use(Какой тип класса использовать) описывает, как выбирать тип класса для использования в вашем приложении.
Behavior of MATLAB Built-In Classes (Поведение встроенных MATLAB-классов)
Если вы создаете, например, объект класса int32и делаете копию этого объекта, результатом являются два независимых объекта, имеющих собственные, не разделяемые данные. Последующий пример создает объект классаint32и назначает его переменнойа, которая копируется вb. Затемавозводится в четвертую степень и результат назначается той же переменнойа. При этомMATLABпереписываетпредыдущее назначение только дляа. Величинаbне меняется:
a = int32(7);% Создание объектаa (со значением 7) класса %int32.
b = a;% Копированиеaвb;bприобретает свои данные (7).
a = a^4; % Обновление объектаaзначением7^4.
b% Запрос на величинуb. Ответ:
b=
7
Результатом рассмотренного кода являются два независимыхобъекта (aиb) классаint32, что типично для численных (value) классовMATLAB.
Графические классы используют метки (handle-имена) для ссылки на объекты. Если вы копируете их, то получаете другую переменную, которая, однако, указываетна тот жесамый объект (точнее – на его данные). Значит, есть толькооднаверсия объекта – его массив данных. Например, если вы создаете объект графической линии и копируете его метку в другую переменную, вы можете установить новые свойства для этой переменной только в рамкахтого же самого(исходного)handle-объекта:
x = 1:10; y = sin(x); % Задание массиваx и функцииy.
h1 = line(x,y);% Создание графического объектаline
% с меткой (handle-именем)h1.
h2 = h1;% Копирование массива данных изh1 вh2.
>>set(h2,'Color','red') % Установка красного цвета
% графического объекта с handle-именемh2.
>>set(h1,'Color','green') % Установка зеленого цвета
% графического объекта с именем-меткой h1.
>>delete(h2)% Уничтожение объектаh2.
>>set(h1,'Color','blue')% Установка голубого цвета объекта
% h1. Посколькуh1 иh2 – тот же самый объект (массив
% данных), который уничтожен посредством delete(h2), то
% оператор set(h1,…)ошибочен.MATLAB-реакция на него:
??? Error using ==> set (Ошибка - см.функцию set)
Invalid handle object (Несуществующий handle-объект).
Таким образом, уничтожение handle-объекта с одной меткой автоматически ведет к потере данныхдля всехдругихhandle-копий этого объекта.
Behavior of User-Defined Classes (Поведение user-defined-классов)
Инстанции определенного пользователями (user-defined)value-класса ведут себяаналогичновстроеннымчисленными структурнымклассам, а инстанцииuser-defined-handle-класса ведут себя подобнографическимhandle-объектам, как показано вBehavior of MATLAB Built-In Classes(Поведение встроенныхMATLAB-классов).
Value Classes(Value-классы)
Объекты value-классовпостоянносвязаны только с переменными, которым они назначены. Когда объект копируется, данные объекта также копируются и новый объект становитсяне зависимымот изменений исходного объекта.
Value Class Behavior (Поведение value-класса)
Value-классы полезны, когда объекты назначаются переменным и посылаются функциям (при этом делается копия объекта – фактические параметры передаются формальным).Value-объекты всегда ассоциируются с рабочей областью или временной переменной и исчезают из рассмотрения при уходе переменной из области рассмотрения или обнулении. Ссылка идет только на независимые копии (value-копии) объекта.
Например, пусть вы определили класс полиномов, свойство Coefficientsкоторого хранит коэффициенты полиномов. Учтите, что копии объектов этогоvalue-класса являются не зависимыми друг от друга:
p = polynomial([1 0 -2 -5]);% Создание полинома (value-
% объекта) pс коэффициентами[1 0 -2 -5](значение
% свойства Coefficientsкласса полиномов).
p2 = p;% Копированиеpвp2.
p.Coefficients = [2 3 -1 -2 -3];% Новое назначение
% свойства Coefficientsдляvalue-объектаp.
p2.Coefficients% Запрос на значения коэффициентов объекта
% p2. Ответ:
ans =
1 0 -2 -5 % Ответ показывает независимость копииp2
% полиномиальногоvalue-объекта отp.
Creating a Value Class (Создание value-класса)
Все классы, которые не являютсяподклассами какого-либоhandle-класса,есть value-классы. Следовательно, следующееclassdef-определение по умолчанию создаетvalue-класс, названныйmyValueClass:
classdef myValueClass% Value-класс, так как здесь нет
% указаний на какой-либо handle-класс.
...
end
Handle Classes (Handle-классы)
Handle-классы используют метки (handle-имена,handle-идентификаторы или простоhandle) для ссылок на свои объекты (на данныеэтих объектов). Метка является переменной, которая идентифицирует инстанцию класса. Когдаhandle-объект копируется, копируетсяметка (handle), ноне данные, хранимые в свойствах объекта. Копия ссылается к тем же самым данным исходного объекта; если изменяются величины свойств,handle-копии автоматически учитывают эти изменения.
Все handle-классы выведены из абстрактного классаhandleили его подклассов. Выведение из классаhandleили его подкласса позволяет вашему классу:
Наследовать полезные методы (Handle Class Methods- Методы классаhandle);
Определить события и слушателей (Defining Events and Listeners — Syntax and Techniques- Определение событий и слушателей – синтаксис и техника);
Определить динамические свойства (Dynamic Properties — Adding Properties to an Instance - Динамические свойства – добавление свойств к инстанции);
Исполнить графические set- и get-методы (Implementing a Set/Get Interface for Properties – Исполнение set/get-интерфейса для свойств).
Creating a Handle Class (Создание handle-класса)
Ниже показано прямое определение некоторого класса myClassкак handle-подкласса:
classdef myClass < handle
…
end
Смотрите The Handle Base Class(Базовый классhandle) для более полной информации о классеhandleи его методах.
Subclasses of Handle Classes (Подклассы handle-классов)
Если вы создаете подкласс из класса, который сам является handle-классом, ваш подкласс есть такжеhandle-класс. Вам не нужны никакие дополнительные указания на это. Например, следующий классemployeeявляетсяhandle-классом по определению:
classdef employee < handle
...
end
Допустим далее, что вы хотите создать employee-подклассengineer, который должен бытьhandle-классом. Вам не надо указывать на суперклассhandleв определении подкласса:
classdef engineer < employee
...
end
Handle Class Behavior (Поведение handle-классов)
Handleесть объект-метка (handle-имя,handle-идентификатор,handle-метка или просто метка), который ссылаетсяне на своиданные, а наданные другого(исходного или базового) объекта. Когда создается базовый объект,MATLABсоздает его свойства - хранилища величин, и функция-конструктор возвращает метку этого объекта, котораяне имеет, а толькоссылаетсяна исходные данные. Когда метка назначается другой переменной или когда метка посылается в функцию, копируется эта метка (handle-имя), но не базовые исходные данные. Это создает уникальную возможность использовать исходные данные всем копиям одногоhandle-объекта и изменять одно и то же множество данных с помощью любойhandle-копии объекта.
Например, пусть вы имеете определение handle-класса employee, который хранит данные о сотрудниках компании, такие как имена и департамент, в котором они работают:
classdef employee < handle
properties % Свойства-хранилища.
Name = '' % Назначение свойствуName пустой строки.
Department = '';% Назначение свойствуDepartment
% пустой строки.
end
methods
function e = employee(name,dept) % Конструктор
% базового объекта и назначение ему меткиe(создание
% первой копии базового объекта-данных).
e.Name = name;% Установка свойстваName.
e.Department = dept; % Установка свойства
% Department.
end % employee
function transfer(obj,newDepartment) % Здесь
% transfer - функция-метод (трансформер).
obj.Department = newDepartment; % Новое
% назначение свойствуDepartment (перевод
% существующего объекта obj в новую компанию).
end %transfer
end
end
В следующем примере e2являетсяhandle-копией объектаe. Заметьте, что при изменении свойстваDepartmentобъектаeменяется свойствоDepartmentтакже и дляhandle-копииe2:
e = employee('Fred Smith','QE');% Вызовemployee- % конструктора для созданияhandle-объектаe.
e2 = e;% Копирование объекта e вe2.
transfer(e,'Engineering') % Вызов трансформера для e.
e2.Department% Запрос по департаменту объектаe2. Ответ на
% запрос:
ans =
Engineering % Ответ показывает, что характеристики дляe2
% и e– одни и те же.
Если бы класс employeeбыл быvalue-классом, методtransferмог бы модифицировать только базовый объект e:
e = transfer(e,'Engineering');
При этом копия e2, являясь не зависимой отe, не получила бы изменения для свойстваDepartment.
Deleting Handles (Уничтожение handle-имен)
Вы можете уничтожить handle-объекты прежде, чем они становятся недоступными для функцииdelete. Уничтожение одной метки объектаhandle-класса делает недействительными все егоhandle-имена. Например, для предыдущего случая:
delete(e2)% Уничтожение метки e2.
e.Department% Обращение к свойствуDepartmenthandle-
% объекта e. Ответ на данный запрос:
??? Invalid or deleted object(Неверный либо уничтоженный объект).
Вызов функции delete дляhandle-объекта приводит к вызову его деструктор-метода (delete-метода), определенногоhandle-классом специально для таких объектов. СмотритеHandle Class Delete Methods(Delete-методыhandle-классов) для дополнительной информации о методах уничтоженияhandle-объектов.
Which Kind of Class to Use(Какой тип класса использовать)
В этом разделе: |
Examples of Value and Handle Classes (Примеры value- и handle-классов);
When to Use Handle Classes (Когда использовать handle-классы);
When to Use Value Classes (Когда использовать value-классы).
|
Examples of Value and Handle Classes (Примеры value- и handle-классов)
Handle- иvalue-классы полезны в различных ситуациях. Например,value-классы позволяют вам создать классы, которые имеют ту же семантику, что и числовыеMATLAB-классы.
Примеры по данной теме:
Example — A Polynomial Class(Пример – класс полиномов) иExample — Representing Structured Data(Пример – представление структурированных данных) дают сведения оvalue-классах;
Handle-классы позволяют вам создать объекты, разделяемые (используемые) многими функциями или другими объектами.Handle-объекты обеспечивают более гибкое взаимодействие между собой;
Example — Implementing Linked Lists(Пример – исполнение связных списков) иDeveloping Classes — Typical Workflow(Создание классов – типовой рабочий процесс) предоставляют примерыhandle-классов.
When to Use Handle Classes (Когда использовать handle-классы)
Вам следует использовать handle-классы, когда:
Нет двух инстанций класса, имеющих совершенно одинаковые состояния, что не дает возможность считать их точными копиями. Например:
Копия графического объекта (такого, как линия) имеет другую позицию в списке потомков по сравнению с оригиналом;
Узлы в списке или дереве имеют специфическое соединение – нет двух узлов с одинаковыми связями;
Класс представляет физические уникальные объекты такие, как последовательные порты или принтеры, когда объекты или их состояния не могут существовать как MATLAB-переменные (независимые копии исходных объектов), ноhandle-имена таких объектовмогут бытьпеременными;
Класс определяет события и уведомляет их слушателей, когда случаются эти события (события и метод уведомления notify, как и методaddlistenerрегистрации слушателей,определенытолькодляhandle-классов);
Класс выведен из класса dynamicprops(handle-подкласс), когда инстанции могут определять свойства динамически;
Класс выведен из класса hgsetget (handle-подкласс), когда можно организоватьset/getинтерфейс в графическомhandle-стиле.
When to Use Value Classes (Когда использовать value-классы)
Инстанции value-классов ведут себя подобноMATLAB-переменным (у каждой копии объекта свой набор данных). Пример использования таких классов - формирование типовых структур данных. Например, вы хотите создать класс для представления полиномов. Этот класс определяет свойства для хранения коэффициентов и выполняет общие для всех объектов данного класса методы, такие как сложение или умножение полиномов.
Копии полиномов в данном случае, опираясь на один и тот же базовый формат класса полиномов, имеют свой наборкоэффициентов. Тогда операции с разными копиями, хотя соответствуют общим методам класса полиномов, в действительности используют разные наборы данных. Смотрите Subclassing MATLAB Built-In Classes(Подклассы встроенныхMATLAB-классов) для более подробной информации оvalue-классах.