Разработка классов - типичный рабочий процесс

Формулировка класса

Этот пример обсуждает, как приблизиться к разработке и реализации класса. Цель этого класса состоит в том, чтобы представлять знакомую концепцию (банковский счет). Однако можно применить тот же подход к большинству проектов класса.

Чтобы разработать класс, который представляет банковский счет, сначала определите элементы данных и операции, которые формируют вашу абстракцию банковского счета. Например, банковский счет имеет:

  • Номер счета

  • Баланс счета

  • Состояние (открытый, закрытый, и т.д.)

Необходимо выполнить определенные операции на банковском счете:

  • Создайте объект для каждого банковского счета

  • Внесите деньги

  • Заберите деньги

  • Сгенерируйте оператор

  • Сохраните и загрузите объект BankAccount

Если баланс является слишком низким, и вы пытаетесь забрать деньги, банковский счет широковещательно передает уведомление. Когда это событие имеет место, банковский счет широковещательно передает уведомление другим сущностям, которые разработаны, чтобы прислушаться к этим уведомлениям. В этом примере упрощенная версия программы менеджера учетных записей выполняет эту задачу.

В этом примере программа менеджера учетных записей определяет состояние всех банковских счетов. Эта программа контролирует баланс счета и присваивает одно из трех значений:

  • открытый Баланс счета является положительным значением

  • overdrawn — Баланс счета превышен ограничения, но на 200$ или меньше.

  • closed — Баланс счета превышен ограничения больше чем на 200$.

Эти функции задают требования классов AccountManager и BankAccount. Включайте только, какая функциональность требуется, чтобы достигать ваших определенных целей. Поддержите специальные типы учетных записей путем разделения на подклассы BankAccount и добавления более определенных опций к подклассам. Расширьте AccountManager как требуется, чтобы поддержать новые типы учетных записей.

Определение компонентов класса

Классы хранят данные в свойствах, реализуют операции с методами и поддерживают уведомления с событиями и прослушивателями. Вот то, как BankAccount и классы AccountManager задают эти компоненты.

Данные класса

Класс задает эти свойства сохранить номер счета, баланс счета и состояние учетной записи:

  • AccountNumber — Свойство сохранить номер, идентифицирующий определенную учетную запись. MATLAB® присваивает значение этому свойству, когда вы создаете экземпляр класса. Только методы класса BankAccount могут установить это свойство. Атрибутом SetAccess является private.

  • AccountBalance — Свойство сохранить текущий баланс учетной записи. Операция класса внесения и удаления денег присваивает значения этому свойству. Только методы класса BankAccount могут установить это свойство. Атрибутом SetAccess является private.

  • AccountStatus — Класс BankAccount задает значение по умолчанию для этого свойства. Методы класса AccountManager изменяют это значение каждый раз, когда значение AccountBalance падает ниже 0. Атрибут Access указывает, что только AccountManager и классы BankAccount имеют доступ к этому свойству.

  • AccountListener — Устройство хранения данных для прослушивателя события InsufficentFunds. Сохранение объекта BankAccount не сохраняет это свойство, потому что необходимо воссоздать прослушиватель при загрузке объекта.

Операции класса

Эти методы реализуют операции, заданные в формулировке класса:

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

  • deposit — Обновляет свойство AccountBalance, когда транзакция депозита происходит

  • withdraw — Обновляет свойство AccountBalance, когда транзакция вывода происходит

  • getStatement — Информация об отображениях об учетной записи

  • loadobj Воссоздает прослушиватель менеджера учетных записей, когда вы загружаете объект из MAT-файла.

События класса

Программа менеджера учетных записей изменяет состояние банковских счетов, которые имеют отрицательные балансы. Чтобы реализовать это действие, класс BankAccount инициировал событие, когда вывод приводит к отрицательному балансу. Поэтому инициирование события InsufficientsFunds происходит из метода withdraw.

Чтобы задать событие, задайте имя в блоке events. Инициируйте событие вызовом метода класса Handle notify. Поскольку InsufficientsFunds не является предопределенным событием, можно назвать его с любым вектором char и инициировать его с любым действием.

Реализация класса BankAccount

Важно гарантировать, что существует только один набор данных, сопоставленных с любым объектом класса BankAccount. Вы не хотели бы независимые копии объекта, который мог иметь, например, различные значения для баланса счета. Поэтому реализуйте класс BankAccount как класс Handle. Все копии данного объекта указателя относятся к тем же данным.

Резюме класса BankAccount

Класс BankAccountОбсуждение
classdef BankAccount < handle

Класс Handle, потому что должна быть только одна копия любого экземпляра BankAccount.Comparison of Handle and Value Classes

   properties (Access = ?AccountManager)
        AccountStatus = 'open'
   end

AccountStatus содержит состояние учетной записи, определенной текущим балансом. Доступ ограничивается классами AccountManager и BankAccount. Доступ для членов класса

   properties (SetAccess = private)
      AccountNumber
      AccountBalance
   end
   properties (Transient)
      AccountListener
   end

Доступ к свойству AccountStatus методами класса AccountManager.

Свойства AccountNumber и AccountBalance имеют частный доступ к набору.

AccountListener property является переходным, таким образом, указатель прослушивателя не сохранен.

Смотрите задают Атрибуты свойств.

   events
      InsufficientFunds
   end

Класс задает событие под названием InsufficentFunds. метод withdraw инициировал событие, когда баланс счета становится отрицательным.

Для получения информации о событиях и прослушивателях, смотрите События.

   methods

Блок обычных методов. См. Методы и Функции для синтаксиса.

      function BA = BankAccount(AccountNumber,InitialBalance)
         BA.AccountNumber = AccountNumber;
         BA.AccountBalance = InitialBalance;
         BA.AccountListener = AccountManager.addAccount(BA);
      end

Конструктор инициализирует значения свойств с входными параметрами.

AccountManager.addAccount является статическим методом класса AccountManager. Создает прослушиватель для события InsufficientFunds и хранит указатель прослушивателя в свойстве AccountListener.

      function deposit(BA,amt)
         BA.AccountBalance = BA.AccountBalance + amt;
         if BA.AccountBalance > 0
            BA.AccountStatus = 'open';
         end
      end

deposit настраивает значение свойства AccountBalance.

Если AccountStatus является closed, и последующий депозит приносит AccountBalance в положительную область значений, то AccountStatus сбрасывается к open.

      function withdraw(BA,amt)
         if (strcmp(BA.AccountStatus,'closed')&& ...
            BA.AccountBalance < 0)
            disp(['Account ',num2str(BA.AccountNumber),...
               ' has been closed.'])
            return
         end
         newbal = BA.AccountBalance - amt;
         BA.AccountBalance = newbal;
         if newbal < 0
            notify(BA,'InsufficientFunds')
         end
      end

Свойство Updates AccountBalance. Если значение баланса счета отрицательно в результате вывода, notify инициировал событие InsufficentFunds.

Для получения дополнительной информации о прослушивателях смотрите Синтаксис Событий и Прослушивателей.

      function getStatement(BA)
         disp('-------------------------')
         disp(['Account: ',num2str(BA.AccountNumber)])
         ab = sprintf('%0.2f',BA.AccountBalance);
         disp(['CurrentBalance: ',ab])
         disp(['Account Status: ',BA.AccountStatus])
         disp('-------------------------')
      end

Отобразите выбранную информацию об учетной записи.

   end
   methods (Static)

Конец обычного блока методов.

Начало блока статических методов. Смотрите Статические методы

      function obj = loadobj(s)
         if isstruct(s)
            accNum = s.AccountNumber;
            initBal = s.AccountBalance;
            obj = BankAccount(accNum,initBal);
         else
            obj.AccountListener = AccountManager.addAccount(s);
         end
      end

Метод loadobj:

  • Если операция загрузки перестала работать, создайте объект из struct.

  • Воссоздает прослушиватель с помощью недавно созданного объекта BankAccount в качестве источника.

Для получения дополнительной информации о сохранении и загружаемых объектах, смотрите, Сохраняют и Процесс Загрузки для Объектов

   end
end

Конец блока статических методов

Конец classdef

 Расширьтесь для кода класса

Формулировка класса AccountManager

Цель класса AccountManager состоит в том, чтобы предоставить услуги учетным записям. Для класса BankAccount класс AccountManager прислушивается к выводу, который заставляет баланс, заскакивают в отрицательную область значений. Когда объект BankAccount инициировал событие InsufficientsFunds, AccountManager сбрасывает состояние учетной записи.

Класс AccountManager не хранит данных, таким образом, ему не нужны свойства. Объектно-ориентированная память BankAccount указатель объекта прослушивателя.

AccountManager выполняет две операции:

  • Присвойте состояние каждой учетной записи в результате вывода

  • Добавляет учетная запись к системе путем контроля баланса счетов.

Компоненты класса

Класс AccountManager реализует два метода:

  • assignStatus — Метод, который присваивает состояние объекту BankAccount. Служит обратным вызовом прослушивателя.

  • addAccount — Метод, который создает прослушиватель InsufficientFunds.

Реализация класса AccountManager

Класс AccountManager реализует оба метода как статичные, потому что нет никакой потребности в объекте AccountManager. Эти методы работают с объектами BankAccount.

AccountManager не предназначается, чтобы быть инстанцированным. Разделение функциональности класса AccountManager от класса BankAccount обеспечивает большую гибкость и расширяемость. Например, выполнение так позволяет:

  • Расширьте класс AccountManager, чтобы поддержать другие типы учетных записей при хранении отдельных классов учетной записи простыми и специализированными.

  • Измените критерии состояния учетной записи, не влияя на совместимость сохраненных и загруженных объектов BankAccount.

  • Разработайте суперкласс Account, который факторизует то, что характерно для всех учетных записей, не требуя, чтобы каждый подкласс реализовал функциональность ведения счетов

Резюме класса AccountManager

Класс AccountManagerОбсуждение
classdef AccountManager

Этот класс задает прослушиватель события InsufficentFunds и обратный вызов прослушивателя.

   methods (Static)

Нет никакой потребности создать экземпляр этого класса, таким образом, заданные методы статичны. Смотрите Статические методы.

   function assignStatus(BA)
      if BA.AccountBalance < 0
         if BA.AccountBalance < -200
            BA.AccountStatus = 'closed';
         else
            BA.AccountStatus = 'overdrawn';
         end
      end
   end

Метод assignStatus является обратным вызовом для прослушивателя события InsufficentFunds. Это определяет значение свойства AccountStatus объекта BankAccount на основе значения свойства AccountBalance.

Конструктор класса BankAccount вызывает метод addAccount AccountManager, чтобы создать и сохранить этот прослушиватель.

   function lh = addAccount(BA)
      lh = addlistener(BA, 'InsufficientFunds', ...
         @(src, ~)AccountManager.assignStatus(src));
   end

addAccount создает прослушиватель для события InsufficentFunds, которое задает класс BankAccount.

См. Управление жизненным циклом приемника

   end
end

Операторы end для methods и для classdef.

 Расширьтесь для кода класса

Используя объекты BankAccount

Класс BankAccount, в то время как чрезмерно простой, демонстрирует, как классы MATLAB ведут себя. Например, создайте объект BankAccount с номером счета и начальным депозитом 500$:

BA = BankAccount(1234567,500)
BA = 

  BankAccount with properties:

      AccountNumber: 1234567
     AccountBalance: 500
    AccountListener: [1x1 event.listener]

Используйте метод getStatement, чтобы проверить состояние:

getStatement(BA)
-------------------------
Account: 1234567
CurrentBalance: 500.00
Account Status: open
-------------------------

Сделайте вывод в 600$, который приводит к отрицательному балансу счета:

withdraw(BA,600)
getStatement(BA)
-------------------------
Account: 1234567
CurrentBalance: -100.00
Account Status: overdrawn
-------------------------

Вывод за 600$ инициировал событие InsufficientsFunds. Текущие критерии, заданные классом AccountManager, приводят к состоянию overdrawn.

Сделайте другой вывод в 200$:

withdraw(BA,200)
getStatement(BA)
-------------------------
Account: 1234567
CurrentBalance: -300.00
Account Status: closed
-------------------------

Теперь AccountStatus был установлен в closed прослушивателем, и дальнейшие попытки сделать вывод блокируются, не инициировав событие:

withdraw(BA,100)
Account 1234567 has been closed.

Если AccountBalance возвращен в положительное значение депозитом, то AccountStatus возвращен, чтобы открыться, и вывод позволен снова:

deposit(BA,700)
getStatement(BA)
-------------------------
Account: 1234567
CurrentBalance: 400.00
Account Status: open
-------------------------
Была ли эта тема полезной?