MATLAB.Exponenta
–Û·Ë͇ Matlab&Toolboxes

MATLAB

В.Г.Потемкин "Введение в Matlab" (v 5.3)
Глава 8. Объектно-ориентированное программирование

  В оглавление книги \ К следующему разделу \ К предыдущему разделу \ Предметный указатель

8.1.  Объекты и классы

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

В системе MATLAB определены 5 классов объектов:

double Числовые массивы и матрицы, заданные в арифметике с плавающей точкой в формате удвоенной точности.
sparse Двумерные действительные или комплексные разреженные матрицы
char Массивы символов
struct Массивы записей (структуры)
cell Массивы ячеек

В свою очередь, пакеты прикладных программ (ППП) семейства продуктов MATLAB дают много примеров определения новых классов объектов. Например, в самой системе MATLAB используется встроенный класс inline, который дает простой способ определения встроенных функций для применения в программах вычисления квадратур, решения дифференциальных уравнений и вычисления нулей функции. ППП Symbolic Math Toolbox базируется на классе объектов sym, который позволяет выполнять вычисления с символьными переменными и матрицами. ППП Control System Toolbox использует класс объектов lti и три его подкласса tf, zpk, ss, которые поддерживают алгоритмы анализа линейных систем с постоянными параметрами.

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

В языке MATLAB отсутствует механизм объявления переменных. Например, оператор A = zeros(10, 10) формирует обычную матрицу размера 10х10, которая является объектом класса double. Точно также оператор s = 'Hello world' создает объект класса char.

То же самое относится и к вновь создаваемым классам. Никаких объявлений переменных или объектов не требуется. Объекты создаются динамически посредством вызова конструктора класса.

Далее в качестве типового рассматривается класс полиномов от одной переменной. Название класса и конструктора класса - polynom.

В этом классе объект является полиномом, например, вида p(x) = x^3 - 2x - 5, который создается в результате вызова конструктора polynom, применяемого к вектору коэффициентов

          p = polynom([1 0 -2 -5])
           p = x^3 - 2*x - 5.

Структура объекта. Один из первых шагов при проектировании нового класса объектов - это выбор структуры данных для рассматриваемого класса. Объекты класса задаются в виде структур. Поля структуры и операции с полями видимы только внутри методов для данного класса.

Например, для класса polynom можно выбрать представление полиномиального объекта в виде вектор-строки, содержащей коэффициенты степеней переменной в убывающем порядке. Так что объект p, принадлежащий классу polynom, - это структура с единственным полем p.c, содержащим коэффициенты. Это поле доступно только для методов, описанных в подкаталоге @polynom.

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

Каталог класса. М-файлы, определяющие методы для объектов данного класса объединяются в каталог класса, название которого задается как @<имя_класса>. Это означает, что М-файлы, определяющие методы для класса polynom, должны быть размещены в каталоге @polynom.

Каталог класса обязательно является подкаталогом каталога, описанного в пути доступа системы MATLAB, но не самим каталогом. Например, каталог @inline - это подкаталог каталога toolbox/matlab/funfun, а каталог @sym - это подкаталог каталога toolbox/symbolic. Новый каталог @polynom должен быть подкаталогом рабочего каталога системы MATLAB или собственного персонального каталога, который должен быть добавлен к пути доступа.

Конструктор класса. Каталог класса должен обязательно содержать М-файл, называемый конструктором класса. Название конструктора должно совпадать с названиями класса и каталога без префикса @. Конструктор создает объекты, используя данные в виде массива записей (структуры) и приписывая им метку класса.

Рассмотрим конструктор полиномов @polynom/polynom.m:

            function  p = polynom(v)
            %POLYNOM Конструктор полиномов.
            % Функция p = polynom(v) формирует полином, используя вектор v,
            % содержащий коэффициенты степеней переменной x, расположенные
            % в убывающем порядке.
                 if nargin == 0
                     p.c = [ ];
                     p = class(p, 'polynom');
                  elseif isa(a, 'polynom')
                     p = v;
                  else
                     p.c = v(:).';
                     p = class(p,'polynom');
                  end

Система MATLAB позволяет вызывать конструктор без аргументов. В этом случае конструктор должен создать шаблон объекта, как правило, с пустыми полями. Также возможно, что конструктор будет вызываться с аргументом входа, который уже является объектом данного класса. В этом случае конструктор обычно возвращает входной аргумент. Функция isa проверяет эту ситуацию. Если аргумент входа существует и не принадлежит классу polynom, то он переформируется так, чтобы быть вектором-строкой и присвавается полю .c результата. И наконец, функция class используется, чтобы приписать метку результату, которая определяет его как polynom.

Следующий оператор является примером использования конструктора polynom

              p = polynom([1 0 -2 -5])
               p = x^3 - 2*x - 5

и формирует полином с заданными коэффициентами.

В общем виде функция конструктора удовлетворяет следующим свойствам:

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

Функции isa и class. Эти функции используются конструктором, но могут применяться и вне каталога класса.

Функция isa(a, 'class_name') проверяет, принадлежит ли объект a данному классу.

Пример.
Каждое из следующих выражений истинно

isa(pi, 'double') isa('hello', 'char') isa(p, 'polynom')
ans = 1 ans = 1 ans = 1

При использовании вне контекста методов функция class допускает только один аргумент.

Команда class(a) возвращает строку, содержащую имя класса для объекта a.

Пример.
Последовательность операторов возвращает соответственно

class(pi) class('hello') class(p)
ans = 'double' ans ='char' ans =''polynom'

Объекты и массивы. В системе MATLAB5 к основному объекту системы - массиву чисел добавлены новые объекты struct и cell. Поскольку объект класса описывается структурой, то допустимы следующие способы использования массива в качестве объекта некоторого класса:

  • поле объекта - массив;
  • объект - массив;
  • элементы массива - объекты некоторого класса.

Рассмотрим эту концепцию на примере полиномов Чебышева, алгоритм построения которых описывается следующими рекуррентными соотношениями:

             T0 (x) = 1
             T1 (x) = x
             Tn+1 (x) = 2 x Tn (x) -Tn-1 (x), n > 1

Если поле объекта - массив, то объект polynom, описанный выше, уже имеет в своей структуре поле, которое является массивом, в данном случае вектор-строкой, содержащей полиномиальные коэффициенты. Понятие “полиномиальные” можно обобщить так, чтобы сами коэффициенты также были векторами. Тогда объект polynom должен иметь поле p.c, которое являлось бы либо двумерным массивом, либо массивом ячеек для размещения векторов коэффициентов. Все методы для такого обобщенного объекта должны обрабатывать такие коэффициенты. Это - возможно не лучший способ представления полиномиальной последовательности, хотя это вполне жизнеспособная структура данных для таких объектов.

Если сам объект - массив, то объект polynom - это массив структур. Внутри методов полиномы должны обозначаться как p(k), и каждый полином должен иметь собственное поле коэффициентов p(k).с. Каждый метод должен использовать цикл для обработки всех полиномов последовательности. Это усложняет применение методов, но упрощает работу с объектами.

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

Рассмотрим реализацию последнего подхода. Введем аргумент x:

            x = polynom([1 0])
             x = x

Сгенерируем и сохраним в массиве ячеек T 10 первых полиномов Чебышева:

             T{1} = 1;
             T{2} = x;
             for n = 2:11
                T{n+1} = 2*x*T{n} - T{n-1};
            end

В результате будут сгенерированы следующие полиномы:

            for n = 2:11
                 T{n}
             end

             ans = x
             ans = 2*x^2 - 1
             ans = 4*x^3 - 3*x
             ans = 8*x^4 - 8*x^2 + 1
             ans = 16*x^5 - 20*x^3 + 5*x
             ans = 32*x^6 - 48*x^4 + 18*x^2 - 1
             ans = 64*x^7 - 112*x^5 + 56*x^3 - 7*x
             ans = 128*x^8 - 256*x^6 + 160*x^4 - 32*x^2 + 1
             ans = 256*x^9 - 576*x^7 + 432*x^5 - 120*x^3 + 9*x
             ans = 512*x^10 - 1280*x^8 + 1120*x^6 - 400*x^4 + 50*x^2 - 1

Построение последнего из них показывает, что на интервале [-1 1] он напоминает гребень и характеризуется быстрым ростом вне этого интервала.

            plot(T{11})

ris801.gif (3918 bytes)

Рис. 8.1

Преобразование классов. Вызов функции преобразования класса имеет вид

                b = class_name(a),

где a - объект некоторого класса, отличного от class_name. В этом случае система MATLAB ищет метод с именем class_name в каталоге классов для объекта a. Такой метод преобразовывает объект одного класса в объект другого класса. Если входной объект уже является объектом класса class_name, то система MATLAB вызывает функцию конструктора, который просто возвращает этот вход.

Две из наиболее важных функций преобразования классов - это double и char. Преобразование к классу double создает традиционный массив системы MATLAB, хотя это может и не отражать требуемого соответствия для некоторых классов. Преобразование к классу char полезно для вывода на печать.

Для класса объектов polynom функция преобразования к классу double - это очень простой М-файл @polynom/double.m, который восстанавливает вектор коэффициентов:

            function c = double(p)
               % POLYNOM/DOUBLE Преобразование объекта polynom в вектор
               % коэффициентов.
               % Функция c = DOUBLE(p) преобразовывает объект polynom в вектор c,
               % содержащий коэффициенты полинома по степеням переменной x
               % в убываающем порядке.
           c = p.c;

Для ранее рассмотренного полинома функция возвращает следующий вектор коэффициентов

            double(p)
            ans = 1 0 -2 -5

Преобразование к классу char - это ключевой метод, потому что он формирует строку символов, состоящую из степеней независимой переменной x. Фактически, как только переменной x присвоено значение, строка становится синтаксически правильным выражением системы MATLAB.

В данном случае это метод @polynom/char.m.

             function s = char(p)
             % POLYNOM/CHAR CHAR(p) формирует строковое представление для полинома
             p. c = p.c;
             if all(c == 0)
                 s = '0';
              else
                 d = length(p.c)-1;
                 s = [ ];
                 for a = c;
                    if a ~= 0;
                      if ~isempty(s)
                         if a > 0
                            s = [s ' + '];
                         else
                            s = [s ' - '];
                            a = -a;
                         end
                      end
                      if a ~= 1 | d == 0
                         s = [s num2str(a)];
                         if d > 0
                            s = [s '*'];
                        end
                      end
                      if d >= 2
                         s = [s 'x^' int2str(d)];
                      elseif d == 1
                         s = [s 'x'];
                      end
                    end
                    d = d - 1;
                end
              end

Для ранее рассмотренного полинома функция

           char(p)

возвращает результат

            ans = x^3 - 2*x - 5.

Вывод на терминал. Метод с именем display вызывается всякий раз, когда оказывается, что исполняемый оператор не заканчивается точкой с запятой. Для многих классов метод display может просто выводить на экран имя переменной, а затем использовать конвертор char, чтобы печатать содержимое или значение переменной. Для этого служит метод @polynom/display.m. Тело этой функции может быть без изменения использовано в каталогах других методов.

           function display(p)
       % POLYNOM/DISPLAY Вывести на экран терминала объект класса polynom.
           disp(' ');
           disp([inputname(1),' = '])
           disp(' ');
           disp([' ' char(p)]) disp(' ');

Пример.

            display(p)
             p = x^3 - 2*x - 5

При работе с полиномами полезно иметь объект x, который представляет собой независимую переменную x. Это реализуется оператором

              x = polynom([1 0])
               x = x

  В оглавление книги \ К следующему разделу \ К предыдущему разделу \ Предметный указатель

 


Поиск по сайту:

Система Orphus

Яндекс.Метрика