
- •Часть 3
- •Введение
- •Indexing Functions (Индексирующие функции);
- •1 12 3 4 % Данные double-части объекта md.
- •InPutNames % cell array of strings (массив ячеек строк) – имена
- •Interfaces and Abstract Classes (Интерфейсы и абстрактные классы)
- •Interface Properties and Methods (Интерфейс свойств и методов)
- •Interface Guides Class Design (Интерфейс руководит разработкой класса)
- •Implementing the zoom Method (Исполнение метода zoom)
- •Inheritance of Properties (Наследование свойств)
- •Implementing the PostSet Property Event and Listener (Исполнение PostSet-события свойства и слушателя) показывает пример слушателя свойств.
- •Приложение
- •Implementing a Set/Get Interface for Properties (Исполнение set/get-интерфейса для свойств)…....12
- •Indexing Functions (Индексирующие
- •Inheritance of Properties (Наследование событий)…..........................................................................................54
- •Часть3 Редактор р.К. Мангутова
Министерство образования и науки Российской Федерации
Рязанский государственный радиотехнический университет
В.Ф. ОДИНОКОВ
MATLAB R2008a. КЛАССЫ
Часть 3
Учебное пособие
Рязань 2012
УДК 519.68 (075.8)
MATLAB R2008a. Классы. Часть 3: учеб. пособие / В.Ф. Одиноков; Рязан. гос. радиотехн. ун-т. - Рязань, 2012. - 80 с.
Рассматриваются основные понятия и элементы MATLAB-классов версии 7.6.0 (R2008a).
Предназначено для студентов специальностей 230201 - "Информационные системы и технологии", 230203 – "Информационные технологии в дизайне", 230204 – "Информационные технологии в медиаиндустрии", бакалавров направления 230400_62 – "Информационные системы и технологии", студентов заочной формы обучения, в том числе по специальности 230201, магистрантов направления 230400_68 - "Информационные системы и технологии" и аспирантов.
Табл. 2. Библиогр.: 4 назв.
В создании пособия принимал участие студент гр. 835 Аникеев Д.В.
Классы, подклассы, объекты, методы
Печатается по решению редакционно-издательского совета Рязанского государственного радиотехнического университета.
Рецензент: кафедра автоматизированных систем управления Рязанского государственного радиотехнического университета (зав. кафедрой д-р техн. наук, проф. Г.И. Нечаев)
Рязанский государственный
радиотехнический университет, 2012
Введение
Без моделирования различных объектов и протекающих в них процессов невозможны почти никакие серьезные исследования и разработки ни в одной из областей знаний. Повышению производительности труда при этом способствуют разнообразные (готовые) системы программной имитации. Одной из таких систем является универсальный пакет МATLAB 7.6 (R2008а), включающий ряд функциональных элементов. Все они представлены соответствующими разделами в путеводителе Help Navigator пакета МATLAB. Среди них важнейшим является раздел МATLAB (Матричная лаборатория). Он содержит язык, методологию и средства программирования. Программирование в системе МATLAB основано на объектно-ориентированной технологии. Последняя изложена в подразделе MATLAB Classes and Object-Oriented Programming (MATLAB-классы и объектно-ориентированное программирование) раздела МATLAB.
Отсутствие русифицированного варианта пакета МATLAB создает значительные трудности при практической работе с ним. Различная литература [1, 2] по системе МATLAB на русском языке только отчасти решает отмеченную проблему, поскольку преследует, в основном, учебные цели. В отличие от этого данное пособие ориентировано на непосредственное общение с МATLAB-документами, так как является продолжением [3, 4] синхронного (в порядке дерева тем путеводителя Help Navigator) перевода-изложения вышеуказанного подраздела системы МATLAB.
Электронный Help-справочник пакета МATLAB, имея цветовое оформление и автоматические ссылки на соответствующие страницы собственной документации, не может быть полностью воспроизведен в черно-белом варианте бумажного носителя данного пособия. Поэтому следует отметить ряд формальных моментов. Так, смысловое ударение на слова и фразы в тексте пособия показано наклонным шрифтом. Цветовое выделение всех заголовков, функций и ключевых слов окна Help в пособии заменено жирным шрифтом. Графические цветовые элементы пакета МATLAB в данном материале различаются только оттенками серого тона. Всё выделенное жирным шрифтом и подчеркнутое в пособии означает автоматический вызов в Help соответствующих страниц пакета при однократном нажатии (клике) левой кнопкой мыши таких ссылок-связей. Специально выделяемые в тексте пособия элементы окружены символами «». Расстановка абзацев и табуляция подчиняются, в основном, правилам окна Help. Шрифт обычного текста пособия - Times New Roman, программный код - Courier New, названия разделов и подразделов - Arial Black. Знаки «%» после строк программного кода означают начало или продолжение неисполняемого текста – комментария; наличие или отсутствие ограничителя «;» в конце строк кода определяется синтаксисом языка MATLAB; многоточие «…» без разрядки (шрифт Times New Roman) означает «и т.д.», «проч.», «и др.»; многоточие «...» с разрядкой (шрифт Courier New) – перенос продолжения строки кода. Понятия «раздел» и «подраздел» условны: любой подраздел как отдельный тематический элемент Help-навигатора является обобщающим разделом для своих внутренних структурных составляющих.
The Handle Base Class (Базовый класс handle)
В этом разделе: |
Building on the Handle Class (Разработка на основе класса handle);
Handle Class Methods (Методы класса handle);
Relational Methods (Методы отношений);
Testing Handle Validity (Проверка handle-правильности);
Handle Class Delete Methods (Delete-методы handle-классов).
|
Building on the Handle Class (Разработка на основе класса handle)
Все handle-классы выводятся из класса handle или его подклассов. Класс handle есть базовый абстрактный класс (суперкласс handle), который означает, что вы не можете создать инстанцию-объект этого класса непосредственно из самого класса handle. Вместо этого вы можете использовать этот класс как суперкласс, когда разрабатываете свой собственный класс (handle-подкласс) для реализации свойств класса handle в конкретных инстанциях. Все классы и их объекты, которые следуют handle-семантике, в иерархии наследования общих характеристик являются производными формами класса handle. Из любых handle-классов (подклассов) можно вывести новые классы (handle-подклассы) для реализации очередных специфических свойств.
Handle Subclasses (Handle-подклассы)
Есть два стандартных handle-подкласса, которые добавляют особые характеристики, когда вы создаете из них свои (user-defined) handle-классы:
-
hgsetget – обеспечивает стандартные set- и get-методы доступа (к свойствам) при разработке интерфейсов в handle-графическом стиле. Смотрите Implementing a Set/Get Interface for Properties (Исполнение set/get-интерфейса для свойств) для получения информации о подклассе hgsetget;
-
dynamicprops — обеспечивает способность к динамическому созданию свойств инстанций. Смотрите Dynamic Properties — Adding Properties (Динамические свойства – добавление свойств) для информации о подклассе dynamicprops.
Выведение из указанных handle-подклассов нового класса означает, что ваш класс тоже становится handle-классом и наследует все параметры класса handle плюс специфические характеристики, обеспечиваемые handle-подклассами hgsetget и dynamicprops.
Handle Class Methods (Методы класса handle)
Любой handle-класс наследует свойства и методы старших handle-классов. Однако базовый класс handle не определяет свойства. Он определяет методы (встроенные handle-методы), обсуждаемые в этом разделе. Какой бы вы ни создавали handle-класс, он наследует эти методы.
Вы можете получить список методов суперкласса handle, посылая его имя встроенной MATLAB-функции methods:
>> methods('handle')% Запрос на методы класса handle.
% Ответ:
Methods for class handle (Методы класса handle):
addlistener findobj gt lt
delete findprop isvalid ne
eq ge le notify
Раздел Defining Events and Listeners — Syntax and Techniques (Определение событий и слушателей – синтаксис и техника) обеспечивает информацию об использовании встроенных handle-методов notify и addlistener.
Раздел Creating Subclasses — Syntax and Techniques (Создание
подклассов – синтаксис и техника) дает основную информацию об определении подклассов.
Relational Methods (Методы отношений)
Встроенные функции-методы (класса handle) отношений между объектами handle-подклассов, например H1 и H2, начинаются с function-линий определений:
function TF = eq(H1,H2)
function TF = ne(H1,H2)
function TF = lt(H1,H2)
function TF = le(H1,H2)
function TF = gt(H1,H2)
function TF = ge(H1,H2)
Во всех приведенных примерах использованы имена общих встроенных MATLAB-функций eq…ge. Класс handle переопределяет эти общие стандартные функции отношений применительно к своим целям. Для каждой пары входных массивов результирующий логический массив того же размера дает оценку отношений соответствующих пар элементов входных массивов. Входные массивы должны быть одного размера или один может быть скаляром. В последнем случае методы используют скалярное расширение, как обычно.
Testing Handle Validity (Проверка handle-правильности)
В классе handle встроенная функция-метод isvalid позволяет определить, действительно ли вы имеете допустимую handle-метку (handle-имя, handle-объект или handle-массивы). Пример:
function B = isvalid(H)
Здесь B - логический массив, в котором каждый элемент есть true только в том случае, если соответствующий элемент в H есть разрешенный handle-объект. Если H не является полностью массивом handle-объектов, каждый элемент в B становится false.
Determining If a Handle Belongs to the Handle Class (Проверка, действительно ли метка принадлежит handle-классу)
Вы можете использовать стандартную функцию isa для определения, принадлежит ли данный идентификатор handle-классу, как противоположность handle-именам Sun Java или Handle Graphics (HG). Например, пусть вы имеете следующий handle-класс button, хранящий Handle Graphics-объекты в свойстве UiHandle:
classdef button < handle
properties
UiHandle
end
methods
function obj = button(pos))% Button-конструктор.
obj.UiHandle = uicontrol...
('Position',pos); % Стандартная функция
% uicontrol формирует графический
% управляющий объект на позиции pos (значение
% свойства Position управляющего HG-объекта).
end
end
end % classdef
Создайте объект, используя button-конструктор:
h = button([50 20 50 20]);
Теперь рассмотрим различие между HG-объектами и объектами handle-класса. Вначале проверим метку h:
>> isa(h,'handle')
Так как для создания h был использован конструктор handle-класса, очевидно:
ans =
1
Далее проверим на соответствие handle-классу свойство UiHandle объекта h:
>> isa(h.UiHandle,'handle') % Ответ:
ans =
0
Этого следовало ожидать, поскольку в button-конструкторе свойству UiHandle назначен Handle Graphics-объект посредством uicontrol. Данное обстоятельство легко подтвердить с помощью встроенной функции ishandle проверки HG-объектов:
>> ishandle(h) % Проверка на соответствие Handle Graphics-
% объектам переменной h. Ответ:
ans =
0
>> ishandle(h.UiHandle) % Проверка на соответствие HG-
% объектам значения свойства UiHandle. Ответ:
ans =
1
Handle Class Delete Methods (Delete-методы handle-классов)
MATLAB-программа уничтожает переменные (объекты) в рабочей области функции, когда:
-
Переменная переназначена;
-
Переменная не используется в остатке функции;
-
Функция окончилась.
Когда MATLAB уничтожает объект, величины, хранящиеся в свойствах объекта, также уничтожаются, и память компьютера, ассоциированная с объектом, возвращается к MATLAB или в операционную систему.
Как только объект уничтожен, любые ссылки на этот объекта в любой рабочей области становятся недействительными, поэтому любая попытка доступа к их содержимому приводит к ошибке.
When to Define a Delete Method for Your Class (Когда определять метод уничтожения для вашего класса)
Вы должны определить требуемые операции обнуления для вашего handle-класса в специальном факультативном delete-методе (иногда называемом деструктором), принимающем имя объекта, которого надо уничтожить. Delete-метод использует имя общей стандартной MATLAB-функции delete и имеет следующую сигнатуру первой function-строки определения:
function delete(h)
где h есть скалярное handle-имя объекта.
Например, вы хотите в своем delete-методе закрыть файл, который был открыт для записи. Для этого внутри создаваемого delete-метода вызывается стандартная функция fclose для файла с идентификатором, хранимым в свойстве FileID объекта obj:
function delete(obj)
fclose(obj.FileID);
end
Using Objects to Write Data to a File (Использование объектов для записи данных в файл) дает пример применения delete-метода.
Object Lifecycle (Время жизни объекта)
MATLAB-программа привлекает delete-метод handle-класса только тогда, когда время жизни объекта закончилось. Жизненный цикл объекта заканчивается, когда объект:
-
Нигде больше не вызывается;
-
Явно уничтожается стандартной функцией delete.
Inside a Function (Внутри функции). Время жизни объекта, ассоциируемого с локальной переменной или входным аргументом внутри функции , задано от момента назначения до момента переназначения, обнуления или отсутствия дальнейших ссылок на него до конца кода функции.
Sequence During Handle Object Destruction (Последовательность уничтожения handle-объектов)
Когда handle-объект уничтожается (явно или по окончании жизненного цикла), MATLAB привлекает delete-методы в следующей последовательности:
-
Delete-метод для класса объекта.
-
Delete-метод для каждого базового класса, начиная с ближайшего класса и заканчивая наиболее главным базовым классом.
MATLAB привлекает delete-методы суперклассов в порядке подчинения, определенном в классе. Например, следующее определение класса специфицирует supclass1 прежде, чем supclass2, поэтому delete-метод для supclass1 вызывается прежде delete-метода класса supclass2:
classdef myClass < supclass1 < supclass2
Delete-метод суперкласса не может вызывать методы или свойства, принадлежащие подклассу.
После вызова каждого delete-метода handle-объекта величины свойств, принадлежавших классу, чей delete-метод был вызван, уничтожаются. Уничтожение величин свойств, которые содержат другие handle-объекты, вызывает delete-методы этих объектов.
Restricting Object Deletion (Ограничение уничтожения объектов).
Класс может предотвратить явное уничтожение объектов извне установкой атрибута Access их delete-метода в private. В этом случае уничтожение возможно только методами класса (его объектов).
Аналогично, если атрибут Access delete-метода установлен в protected, явное уничтожение объектов данного класса разрешено только методами класса или его подклассов.
Finding Handle Objects and Properties (Поиск handle-объектов и свойств)
В этом разделе: |
Finding Handle Objects (Поиск handle-объектов);
Finding Handle Object Properties (Поиск свойств handle-объекта).
|
Finding Handle Objects (Поиск handle-объектов)
Встроенный метод findobj класса handle позволит вам найти в массиве H handle-объектов те объекты, которые удовлетворяют определенным условиям <conditions>, представленным в команде. Этот метод использует тот же самый синтаксис, что и стандартная MATLAB-функция findobj, за исключением того, что первый аргумент должен быть handle-массивом:
function HM = findobj(H,<conditions>)
Данный метод возвращает массив handle-имен, удовлетворяющих специфицированным условиям.
Finding Handle Object Properties (Поиск свойств handle-объекта)
Встроенный стандартный метод findprop класса handle возвращает объекты класса meta.property для специфицированных объектов и их свойств, например:
function mp = findprop(h,'PropertyName')
В данном случае метод findprop возвращает объект класса meta.property, ассоциированный со свойством PropertyName, определенным классом для h, или оно может быть динамическим свойством, созданным методом addprop встроенного класса dynamicprops.
Вы можете использовать возвращенный объект класса meta.property для получения некоторой информации о свойствах, например узнать установку любого из атрибутов свойств. Следующие выражения определяют, что установка атрибута Dependent свойства AccountStatus есть false:
ba = BankAccount(007,50,'open'); % Создание
% BankAccount-объекта.
mp = findprop(ba,'AccountStatus'); % get
% meta.property object (получение meta.property-объекта) -
%) для свойства AccountStatus объекта ba.
mp.Dependent % Запрос на атрибут Dependent свойства
% AccountStatus объекта ba (запрос на свойство
% Dependent информационного meta- объекта mp,
% соответствующего атрибуту Dependent свойства
% AccountStatus исходного объекта ba). Ответ:
ans =
0 % Значение атрибута Dependent свойства AccountStatus
% объекта ba есть false.
Obtaining Information About Classes with Meta-Classes (Получение информации о классах с помощью meta-классов) дает более подробную информацию о meta-классах.
Implementing a Set/Get Interface for Properties (Исполнение set/get-интерфейса для свойств)
В этом разделе: |
The Standard Set/Get Interface (Стандартный set/get-интерфейс);
Property Get Method (Get-метод свойств);
Property Set Method (Set-метод свойств);
Subclassing hgsetget (Создание hgsetget-подкласса).
|
The Standard Set/Get Interface (Стандартный set/get-интерфейс)
MATLAB-подсистема Handle Graphics (Handle-Графики - HG) выполняет роль интерфейса, базируясь на готовых стандартных MATLAB-функциях (методах) set и get (для ознакомления с ними воспользуйтесь этими автоматическими ссылками), которые позволяют вам установить или запросить величину свойств графических handle-объектов. Подкласс hgsetget класса handle обеспечивает исполнение таких встроенных регламентированных методов (см. таблицу методов этого подкласса), которые могут быть наследуемы вашим handle-классом и дают ту же функциональность его инстанциям (при этом инстанции класса handle не являются Handle Graphics-объектами).
Замечание. Стандартные set- и get-методы, представленные в этом разделе, отличаются от set/get-методов доступа к свойствам, которые вы создаете сами для контроля того, что произойдет, когда будет сделана любая попытка установки или запроса величины свойства вашего (user-defined) класса. Смотрите Controlling Property Access (Контроль доступа к свойствам) для информации о методах доступа к свойствам user-defined-классов. |
Property Get Method (Get-метод свойств)
Стандартный get-метод для инстанций класса hgsetget возвращает величины свойств handle-объектов. Ниже даны два варианта первых строк определений для get-методов:
function SV = get(h) % Специфицирован handle-объект h.
function CV = get(H,prop) % Специфицированы массив
% (или скаляр) handle-объектов H и имя (имена) prop свойств.
-
Если вы не специфицировали имена свойств (первая строка выше), get возвращает структуру struct. Каждое поле структуры относится к свойству, определенному классом в h. Величина каждого поля есть значение соответствующего свойства в h.
-
Если вы специфицировали prop как массив символов, он интерпретируется как имя свойства и get возвращает величину этого свойства, если H есть скаляр (handle-объект), или массив ячеек величин этого свойства, если H есть handle-массив (одна ячейка для одного элемента массива H). Массив ячеек в данном варианте всегда считается вектором-столбцом. Если prop есть массив (ячеек) имен свойств, get возвращает массив (ячеек) величин, содержащий строки и столбцы, где каждая строка соответствует специфицированным в prop свойствам одного элемента в H, а каждый столбец – элементам H для одного свойства в prop.
Property Set Method (Set-метод свойств)
Стандартный set-метод для класса hgsetget назначает величины свойствам handle-объектов. Рассмотрим три варианта строк определений:
function S = set(h)% Специфицирован только handle-объект h.
function info = set(h, prop) % Специфицирован handle-
% объект h и массив (или скаляр) prop свойств.
function set(h,'PropertyName',PropertyValue) % Спе-
% цифицирован handle-объект h и пара
% «имя свойства»/«величина свойства».
Если вы не специфицировали величины свойств, set возвращает массив ячеек возможных величин для каждого свойства, когда величина свойства ограничена конечным перечислением возможных величин.
-
Если вы специфицировали только h, set возвращает структуру с полями для каждого свойства в h и каждое поле содержит либо пустой массив ячеек, либо массив ячеек возможных величин свойств (если есть пределы установки).
-
Если вы специфицировали prop как строку имени свойства, set возвращает либо массив ячеек возможных величин этого свойства, либо пустую ячейку.
-
Если вы специфицировали prop как массив (ячеек) имен свойств, set возвращает вектор-столбец ячеек, в котором каждая ячейка соответствует свойству в prop, и каждая величина ячейки есть массив ячеек возможных величин или пустая ячейка, если нет ограниченного перечисления возможных величин.
Вы можете также организовать пары «имя свойства»/«величина свойства» в set, используя массив ячеек и структуры, как предписано для этой встроенной функции-методе (MATLAB-функции) set.
Subclassing hgsetget (Создание hgsetget-подкласса)
Этот пример создает класс с set/get-интерфейсом и далее (при его использовании) иллюстрирует поведение наследуемых стандартных set/get-методов:
classdef myAccount < hgsetget % subclass hgsetget
% (hgsetget-подкласс).
properties
AccountNumber % «Номер счета» - по умолчанию «пусто»
% (назначение конкретной величины здесь невозможно - % счет еще не открыт).
AccountBalance = 0; % «Баланс счета»; назначение ему
% величины «0» соответствует еще не открытому счету.
AccountStatus % «Статус счета» - по умолчанию «пусто»
% (можно назначить значение, позволяющее открыть счет).
end % properties
methods
function obj = myAccount(actnum, intamount,...
status) % Конструктор myAccount-объектов, где
% можно назначить любые величины свойствам,
% используя принятые аргументы:
obj.AccountNumber = actnum;
obj.AccountBalance = intamount;
obj.AccountStatus = status;
end % myAccount
function obj = set.AccountStatus(obj,val) % Соз-
% данный пользователем (не стандартный) set-метод для
% свойства AccountStatus.
if ~(strcmpi(val,'open') ||...
strcmpi(val,'deficit') ||...
strcmpi(val,'frozen')) % Проверка
% val на недопустимые значения. Если
% так, то вызывается функция error:
error('Invalid value for AccountStatus ')
% Вывод сообщения: «Неверная величина для
% свойства AccountStatus».
end
obj.AccountStatus = val; % Передача val (полученное
%. значение атрибута) свойству AccountStatus.
end % set.AccountStatus
end % methods
end % classdef
Создайте инстанцию класса myAccount:
h = myAccount(1234567,500,'open');
Вы можете запросить величину любого свойства объекта h, используя стандартный наследуемый get-метод класса hgsetget, например:
get(h,'AccountBalance') % Запрос по балансу. Ответ:
ans =
500
Вы можете установить величину любого свойства для h, используя наследуемый стандартный set-метод класса hgsetget, например:
set(h,'AccountStatus','closed') % Попытка установки
% недопустимого значения свойства AccountStatus. Поэтому
% выводится сообщение:
??? Error using ==> (Ошибка –)
myAccount.myAccount>myAccount.set.AccountStatus at 19 (см. код метода set.AccountStatus класса myAccount
в 19)
Invalid value for AccountStatus (Неверная величина для AccountStatus)
Так как user-defined-set-метод для свойства (здесь set.AccountStatus) класса myAccount определен в нем, он вызывается автоматически каждый раз, когда вы используете наследуемый set-метод класса hgsetget (из него выведен класс myAccount). Аргумент val в set-методе класса myAccount берется из встроенной set-команды, если имена свойства в set.AccountStatus и соответствующего аргумента set-команды совпадают. Например (когда obj=h, val='frozen'):
set(h,'AccountStatus','frozen')
Listing All Properties (Список всех свойств)
Стандартный set/get-интерфейс позволяет вам отобразить все свойства handle-объекта и их текущие величины, используя get без выходных аргументов (результат запроса не назначается переменным). Например (см. выше инстанцию h класса myAccount),:
>> get(h)% Запрос на свойства handle-объекта h; результат
% не назначается никаким переменным (выходных
% аргументов нет). Ответ:
AccountNumber: 1234567
AccountBalance: 500
AccountStatus: 'open'
Аналогично вы можете получить список устанавливаемых свойств, используя встроенный set-метод:
>> set(h)% Запрос на список свойств handle-объекта h; так как нет
% перечня допустимых значений свойств, именные поля
% структуры свойств содержат только пустые ячейки:
AccountNumber: {}
AccountBalance: {}
AccountStatus: {}
Customizing the Property List (Заказ списка свойств)
Вы можете заказать отображение списков свойств следующими регламентированными методами, допускающими переопределение, класса hgsetget:
-
setdisp – вызывается посредством set, когда вы вызываете set без выходных аргументов и единственный входной параметр содержит handle-массив;
-
getdisp – вызывается посредством get, когда вы вызываете get без выходных аргументов и единственный входной параметр содержит handle-массив.
Building on Other Classes (Конструирование из других классов)
Темы раздела и их краткие характеристики.
Hierarchies of Classes — Concepts Концепты для иерархий классов (Иерархии классов – концепты)
Creating Subclasses — Syntax and Синтаксис и создание подклассов
Techniques (Создание подклассов –
синтаксис и техника)
Modifying Superclass Methods and Как изменить то, что наследуется
Properties (Модификация методов
и свойств суперкласса)
Subclassing from Multiple Classes Использование
(Подклассы многих классов) мультинаследований
Subclassing MATLAB Built-In Расширение встроенных классов
Classes (Подклассы встроенных
MATLAB-классов)
Abstract Classes and Interfaces Использование абстрактных (Абстрактные классы и интерфейсы) классов для создания интерфейсов
Hierarchies of Classes — Concepts (Иерархии классов – концепты)
В этом разделе:
-
Classification (Классификация);
-
Developing the Abstraction (Выделение абстракции);
-
Designing Class Hierarchies (Планирование иерархий классов);
-
Super and Subclass Behavior (Поведение суперклассов и подклассов).
Classification (Классификация)
Организация классов в иерархии упрощает многократное использование кода и, следовательно, повторное использование решений для однотипных задач. Вы можете думать об иерархиях классов как о множествах (супермножества, суперклассы или базовые классы) и подмножествах (подклассы). Например, следующий рисунок показывает, как вы могли бы представить базу данных для служащих с помощью классов:
Продавцы
и Инженеры как подмножества Служащих
Продавцы
и Инженеры как подмножества Служащих
Прода-вцы
Инженеры
Тест-
Инжене-ры
Служащие
Служащие
Продавцы
(есть Служащие)
Инженеры
(есть Служащие)
Тест-Инженеры
(есть Служащие)
Базовый класс
Производные
классы
В начале иерархии находится класс Служащие (Employee). Он содержит данные и операции, которые применяются ко всем служащим. В множестве служащих расположены подмножества компонентов, которые являются служащими более специализированного типа. Эти подмножества представлены на рисунке тремя подклассами разного уровня – Продавцы (Sales People), Инженеры (Engineers) и Тест-Инженеры (TestEngineers).
Developing the Abstraction (Выделение абстракции)
Классы являются абстрактными представителями реальных сущностей или вещей. Когда планируется класс, вам необходимо сформировать абстракцию того, что представляет класс. Рассмотрим абстракцию служащих и их существенные аспекты, представленные классом. Имя (Name), Адрес (Address) и Компания (Department) могут быть общими аспектами для всех служащих.
Когда планируется класс, ваша абстракция должна содержать только те элементы, которые необходимы. Например, цвет волос и размер обуви определенно характеризуют служащих, но, очевидно, не значимы для самого класса. Регион продаж важен только для продавцов, поэтому этот параметр принадлежит только подклассу.
Designing Class Hierarchies (Планирование иерархий классов)
Когда вы планируете систему классов, вы должны определиться с общими данными и функциональностью суперкласса, который вы можете использовать для выведения подклассов. Подклассы наследуют все данные и функциональность суперкласса и дополняются только аспектами, которые уникальны для их целей. Такой подход обеспечивает следующие преимущества:
-
Вы уходите от дублирования кода, который может быть общим для всех классов;
-
Вы можете добавлять или изменять подклассы в любое время без модификации суперкласса или влияния на другие выводимые классы;
-
Если изменения касаются суперкласса (например, всем служащим назначен дополнительно символьный номер), эти изменения автоматически передаются подклассам.
Super and Subclass Behavior (Поведение суперклассов и подклассов).
Подклассы ведут себя подобно суперклассам, потому что они являются специализациями суперкласса. Это обстоятельство упрощает разработку связанных классов, которые ведут себя аналогично, но исполняются по-разному.
A Subclass Is A Superclass (Подкласс есть суперкласс)
Вы обычно можете описать отношения между подклассом и его суперклассом следующим выражением:
«Подкласс есть суперкласс. Например: Инженер есть Служащий»
Отношение утверждает, что подклассы имеют (явно) те же самые свойства, методы и события, что и суперкласс, а также (неявно) любые новые характеристики, определенные подклассом.
A Subclass Object Can be Treated Like a Superclass Object (Объект подкласса может быть интерпретирован как объект суперкласса)
Вы можете послать объект подкласса методу суперкласса, но вы можете иметь доступ только к тем свойствам, которые определены суперклассом. Такое поведение позволяет модифицировать подкласс без влияния на суперкласс.
Следует помнить о двух аспектах поведения суперкласса и подкласса:
-
Методы, определенные в суперклассе могут работать с объектами подкласса;
-
Методы, определенные в подклассе не могут работать с объектами суперкласса;
Поэтому вы можете трактовать Engineer-объект как некоторый Employee-объект, но нельзя Employee-объект заменить Engineer-объектом. Таким образом, как указывалось раньше, любые подклассы и их объекты являются просто производными формами основного (базового) класса (суперкласса).
Creating Subclasses — Syntax and Techniques (Создание подклассов – синтаксис и техника)
В этом разделе: |
Defining a Subclass (Определение подкласса);
Referencing Superclasses from Subclasses (Ссылки на суперклассы из подклассов);
Creating an Alias for an Existing Class (Создание альтернативного имени для существующего класса). |
Defining a Subclass (Определение подкласса)
Для определения класса, который является подклассом другого класса, добавьте суперкласс к classdef-линии после символа «<», например:
classdef classname < superclassname
Когда наследование идет из многих классов, используйте символ «&» для комбинирования суперклассов, например:
classdef classname < super1 & super2
Смотрите Class Member Compatibility (Совместимость компонентов классов) для дополнительной информации о пересечении классов.
Class Attributes (Атрибуты класса)
Подклассы не наследуют атрибуты суперклассов, за исключением атрибута InferiorClasses. Если суперклассы и подкласс определяют атрибут InferiorClasses, полный список подчинения классов включает все определения этого атрибута.
Referencing Superclasses from Subclasses (Ссылки на суперклассы из подклассов)
При создании объекта obj подкласса, вы должны использовать синтаксис obj@baseclass1(args)для инициализации суперкласс-части (здесь baseclass1)объекта obj аргументами args. Например, следующий сегмент определения класса показывает класс stock, который является подклассом класса asset, и инициализацию супер-части stock-объекта s:
classdef stock < asset
methods
function s = stock(...)
s = s@asset(...) % call asset constructor (вызов
% asset-конструктора).
...
end
end
end
Constructing Subclasses (Создание подклассов) дает нужную информацию о конструктор-методах подклассов.
Creating an Alias for an Existing Class (Создание альтернативного имени для существующего класса)
Вы можете создать альтернативное имя для класса, которое позволяет вам ссылаться на класс посредством другого имени. Эта техника аналогична C++ typedef-концепции. Для получения альтернативного имени создайте пустой класс (newclassname – новое имя класса) из вашего существующего класса (oldclassname – старое имя класса):
classdef newclassname < oldclassname
end
Эта техника может быть полезна, когда перезагружаются объекты, которые были сохранены с использованием старого имени класса. Тем не менее, класс таких объектов отражает новое имя. Например, запрос:
class(obj)
возвращает новое имя класса для объекта obj старого класса.
Modifying Superclass Methods and Properties (Модификация методов и свойств суперкласса)
В этом разделе: |
Modifying Superclass Methods (Модификация методов суперкласса);
Modifying Superclass Properties (Модификация свойств суперкласса).
|
Modifying Superclass Methods (Модификация методов суперкласса)
Следует держать в уме важную концепцию, когда разрабатываются классы, в которых объект является также объектом суперкласса (разрабатываемый класс есть подкласс суперкласса). В таком случае вы можете послать объект подкласса в метод суперкласса и метод будет выполнен правильно. В то же самое время вы можете применить специальную дополнительную обработку для определенных аспектов подкласса. Некоторые полезные способы для осуществления этого включают:
-
Вызов метода суперкласса из метода подкласса;
-
Переопределение защищенных методов подкласса в пределах public-суперкласса-метода;
-
Определение одних и тех же именованных методов в суперклассе и подклассе, но использующих разные исполнения.
Extending Superclass Methods (Расширение методов суперкласса)
Методы подкласса могут вызвать методы суперкласса того же имени. Это позволяет вам расширить метод суперкласса в подклассе без существенного переопределения метода суперкласса. Например, пусть подкласс и суперкласс имеют методы, названные foo. Так как имена одинаковые, метод подкласса может вызвать метод суперкласса, но метод подкласса может также выполнить другие шаги прежде и после вызова метода суперкласса для операций с особыми частями подкласса, которые не являются частью суперкласса.
Ниже дан вариант вызова метода foo суперкласса из такого же метода подкласса:
classdef sub < super % Определение подкласса.
methods
function foo(obj) % Определение метода подкласса.
preprocessing steps (шаги до вызова метода суперкласса).
foo@super(obj); % Call superclass foo method -
% вызов метода foo суперкласса.
postprocessing steps (шаги после вызова метода суперкласса).
end
end
end
Смотрите Invoking Superclass Methods in Subclass Methods (Привлечение методов суперкласса в методах подкласса) для большей информации о таком синтаксисе.
Completing Superclass Methods (Комплектование методов суперкласса)
Суперкласс может определять процесс, который выполняется в серии шагов, с использованием защищенного метода (атрибут Access установлен как protected) для любого шага. Подкласс может иметь свои версии защищенных методов, которые выполняют индивидуальные шаги в указанном процессе.
Пример реализации этой технологии (super – будущий суперкласс):
classdef super % Определение класса super.
methods
function foo(obj) % Определение public-метода
% класса super как последовательности шагов.
step1(obj)
step2(obj)
step3(obj)
end
end
methods (Access = protected) % Заказ на protected-
% защиту методов класса super в этом блоке.
function step1(obj) % Определение первого шага с
% защищенным доступом.
superclass version (версия суперкласса)
end
etc. (и т.д.)
end
end
Подкласс класса super не может в данном случае переопределить метод foo (в нем только порядок шагов), он может переопределить только методы, которые вынесены из серии шагов (step1(obj), step2(obj), step3(obj)). Иначе говоря, super-подкласс может уточнить действия по каждому шагу, но не может контролировать порядок шагов. Когда вы посылаете объект super-подкласса в метод foo суперкласса super, MATLAB следит за тем, чтобы исполнялся метод подкласса. Например:
classdef sub < super % Определение super-подкласса sub.
...
methods (Access = protected)
function step1(obj)
subclass version (версия подкласса)
end
etc. (и т.д.)
end
end
Redefining Superclass Methods (Переопределение методов суперкласса)
Если есть необходимость и возможность, вы можете полностью переопределить метод суперкласса. В этом случае суперкласс и подкласс оба должны определить один и тот же именованный метод.
Modifying Superclass Properties (Модификация свойств суперкласса)
Есть только два условия, которые позволяют вам переопределить свойства суперкласса:
-
Атрибут Abstract свойств суперкласса установлен в true;
-
Оба атрибута SetAccess и GetAccess свойства суперкласса установлены в private.
В первом случае суперкласс требует только, чтобы вы определили конкретную версию этого свойства, не противоречащую интерфейсу. Во втором случае только суперкласс имеет доступ к свойству, а подкласс должен использовать свою версию свойства.
Subclassing from Multiple Classes (Организация подкласса из многих классов)
В этом разделе: |
Class Member Compatibility (Совместимость компонентов класса) |
Class Member Compatibility (Совместимость компонентов класса)
Когда вы создаете подкласс, выводимый из многих классов, подкласс наследует свойства, методы и события, определенные всеми суперклассами. Если свойство, метод или событие определены более чем одним суперклассом, не должно быть разночтений во всех определениях. Вы не можете вывести подкласс из двух и более классов, которые определяют несовместимые компоненты.
В следующих разделах описаны различные ситуации, где конфликты имен и определений могут быть разрешены
Property Conflicts (Конфликты свойств)
Если два или более суперкласса определяют свойство с тем же самым именем, по крайней мере, одно из следующих должно быть верным:
-
Во всех или во всех, кроме одного, свойствах атрибуты SetAccess и GetAcess должны быть установлены в private;
-
Свойства имеют одинаковые определения во всех суперклассах (например, когда все суперклассы наследуют свойство из одного базового класса).
Method Conflicts (Конфликты методов)
Если два или более суперкласса определяют методы с одним именем, по крайней мере, одно из следующих должно быть верным:
-
Артибут Access метода должен быть установлен в private так, чтобы только определяющий суперкласс мог иметь доступ к методу;
-
Метод имеет то же самое определение во всех выводимых классах. Это может встретиться, когда все суперклассы наследуют метод из общего базового класса и ни один из суперклассов не переопределяет наследуемое определение;
-
Подкласс переопределяет метод для устранения неопределенности множества определений по всем суперклассам. Это означает, что методы суперкласса не должны иметь атрибут Sealed (Опечатан), установленный в true;
-
Только один суперкласс определяет метод как Sealed, в таком случае определение этого метода принимается подклассом;
-
Суперклассы определяют методы как Abstract и от подкласса зависит определение метода.
Event Conflicts (Конфликты событий)
Если два или более суперклассов определяют события с одинаковыми именами, по крайней мере, одно из следующих должно быть верным:
-
Атрибуты ListenAccess и NotifyAccess событий должны быть установлены в private;
-
Событие должно иметь одно и то же определение во всех суперклассах (например, когда все суперклассы наследуют событие из общего базового класса).
Using Multiple Inheritance (Использование множественного наследования)
Разрешение потенциальных конфликтов, усложняющихся при создании подкласса из многих классов, часто снижает остроту ситуации. Например, проблемы могут возникнуть, когда суперклассы усовершенствуются в последующих версиях и могут обусловливать новые конфликты. Эти потенциальные проблемы могут быть ослаблены, если только один суперкласс не ограничивается, а все другие суперклассы являются классами, в которых все методы - абстрактные и должны быть определены через подкласс или унаследованы из не ограничиваемого суперкласса.
В общем, когда используется множественное наследование, вы должны быть уверены, что все суперклассы остаются свободными от конфликтов в определении.
Subclassing MATLAB Built-In Classes (Создание подкласса для встроенных MATLAB-классов)
В этом разделе: |
MATLAB Built-In Classes (Встроенные MATLAB-классы);
Why Subclass Built-In Classes (Зачем нужны подклассы встроенных классов);
Behavior of Built-In Functions with Subclass Objects (Поведение встроенных функций с объектами подклассов);
Example — Representing Hardware as a Class (Пример – представление оборудования как класс). |
MATLAB Built-In Classes (Встроенные MATLAB-классы)
Встроенные классы представляют фундаментальные свойства данных, таких как числовые массивы, логические массивы и символьные массивы. Другие классы имеют тенденцию к комбинированию данных, принадлежащих к этим фундаментальным классам. Массивы ячеек и структурные массивы являются другими фундаментальными классами.
Встроенные классы определяют методы, которые позволяют вам выполнить многие операции на объектах этих классов. Например, рассмотрим класс double. Язык MATLAB, используя оператор назначения, позволяет вам создавать массивы класса double и выполнять комплексные операции над ними, такие как перемножение матриц, индексация и т.д.
Смотрите Built-In Classes (Data Types) - Встроенные классы (Типы данных) для большей информации об этих классах.
Why Subclass Built-In Classes (Зачем нужны подклассы встроенных классов)
Вы можете вывести классы из большинства встроенных MATLAB-классов. Это полезно, когда вы создаете класс, который обрабатывает, в основном, данные встроенного класса, и хотите использовать методы этого класса непосредственно с объектами вашего класса. Например, если вы создали подкласс встроенного класса double, вы можете использовать объект вашего подкласса везде, где необходима двойная точность.
Классы, которые определяют подсчет и перечисление, могут быть выведены из классов целых значений и, следовательно, наследуют методы, которые позволяют вам осуществлять сравнение и сортировку величин. Например, классы типа int32 поддерживают все методы отношений (eq, ge, gt, le, lt, ne).
Built-In Classes You Cannot Subclass (Встроенные классы, для которых вы не можете создавать подклассы)
Вы не можете создавать подклассы из следующих встроенных MATLAB-классов:
-
char - символьный класс;
-
cell - класс массивов ячеек;
-
struct - класс структур;
-
function_handle - класс handle-функций.
Extending Double (Расширение double)
Встроенный MATLAB-класс double определяет широкий диапазон методов для выполнения арифметических операций, индексации, матричных операций и т.д. Поэтому создание double-подклассов позволяет добавить требуемые специфические качества с использованием многих уже готовых методов (содержащихся в базовом классе double), в которых любой численный класс нуждается для правильного функционирования в MATLAB.
Для примера следующий double-подкласс mydouble добавляет свойство DataHeader (Заголовок данных) для включения описательного текста str в double-объект:
classdef mydouble < double
properties
DataHeader
end
methods
function obj = mydouble(data,str) % Конструктор
% подкласса mydouble.
obj = obj@double(data); % initial the base class
% portion (инициализация части базового класса) -
% вызов double-конструктора для формирования
% суперкласс-части объекта obj.
obj.DataHeader = str; % Текстовая часть объекта.
end
function display(obj) % Display-метод класса mydouble.
disp(obj.DataHeader) % Вывод заголовка объекта obj
% с помощью встроенной MATLAB-функции disp.
display(double(obj)) % built-in display function for
% double (встроенная функция display для
% double) – вывод результата вызова double-конструктора
% с аргументом obj; так как double-конструктор создает
% объект в соответствии с классом double, в этот объект
% не войдет свойство DataHeader, поэтому здесь на экране
% появятся только числовые данные data.
end
end
end
Вы можете создать инстанцию класса mydouble и вызвать любые методы класса double. Заметьте, что mydouble определяет свой собственный display-метод, который вызывает встроенную функцию display. Пример создания mydouble-объекта с текстовым заголовком:
>> md = mydouble(rand(4),'Random numbers') % Нет
% ограничителя «;», поэтому после создания mydouble-
% объекта md будет вызван display-метод класса mydouble:
Random numbers (Случайное число) % Вывод из md.DataHeader
% mydouble-объекта.
ans = % Вывод double-части объекта md - матрица rand(4):
0.4218 0.6557 0.6787 0.6555
0.9157 0.0357 0.7577 0.1712
0.7922 0.8491 0.7431 0.7060
0.9595 0.9340 0.3922 0.0318
Обращение к методу, унаследованному от класса double, возвращает double-данные и, при необходимости, использует display-метод класса double, например:
>> sum(md) % Обращение к методу sum класса double, т.е. к
% double-части объекта md, использующей передаваемые
% ей данные rand(4); так как здесь нет ограничителя «;», будет
% вызван display-метод класса double. Ответ – сумма чисел в
% столбцах матрицы rand(4):
ans =
3.0892 2.4746 2.5718 1.5645
Класс mydouble также унаследовал из double возможность индексного указания double-части mydouble-объектов. Например:
>> md(1:3,1) % Обращение к индексному методу double-части
% (см. Indexing Functions - Индексирующие
% функции) объекта md, т.е. к первым трем элементам первого
% столбца матрицы (данных data) rand(4). Ответ:
ans =
0.4218
0.9157
0.7922
Конкатенация не поддерживается подклассами, которые определяют свои свойства. Это объясняется невозможностью объединения свойств разных объектов. Для дополнительной информации о поведении классов, которые выведены из встроенных классов, смотрите Behavior of Built-In Functions with Subclass Objects (Поведение встроенных функций с объектами подклассов). Ниже дан пример попытки конкатенации двух объектов:
md2 = mydouble(rand(4),'More random numbers');
>> [md md2] % Автоматический вызов встроенной функции
% horzcat горизонтальной конкатенации. Ответ:
??? Error using ==> horzcat (Ошибка – см. код функции horzcat)
Cannot concatenate objects of class mydouble. When a class inherits from a builtin type, concatenation
is only allowed if it does not define any property (Невозможно объединить объекты класса mydouble. Когда класс наследует встроенный тип, конкатенация разрешена только, если он не дает определение какого-либо свойства).
Behavior of Built-In Functions with Subclass Objects (Поведение встроенных функций с объектами подклассов)
Когда вы создаете класс, который выводится из встроенного MATLAB-класса, унаследованная часть данных трактуется как приватное свойство встроенного класса. Это значит, что вы имеете доступ к этим данным только посредством методов встроенного класса или индексацией.
Extending Double (Расширение double) дает пример поведения этого типа.
Встроенные функции, унаследованные от встроенных классов ведут себя по-разному в зависимости от того, какую конкретно функцию вы используете. Следующие разделы описывают каждое поведение: