Объектно-ориентированное программирование
Объектно-ориентированное программирование является важным для разработки OERA-приложений, так как позволяет явно моделировать пользователей, системы и объекты, из которых состоят варианты использования приложения. Классы ABL используются для представления пользователей, системы или объектов. Каждый класс содержит описание данных и реализующий поведение код. Приложение, как правило, это набор классов, которые взаимодействуют друг с другом для реализации вариантов использования.
При проектировании ABL-класса (файл с расширением «.cls») вы должны определить атрибуты класса (представляют данные) и методы класса (представляют поведение). Класс ABL – это определение того, как пользователь, система или объект будут вести себя во время выполнения. В приложении вам необходимо написать код, который будет создавать экземпляры класса. Во время выполнения экземпляр заполняется данными и готов к выполнению требуемых методов в зависимости от вариантов использования.
Например, вы можете создать класс CustomerBE, который моделирует необходимое поведение для бизнес-сущности, представляющей покупателей и связанных с ними наборами заказов. Экземпляр CustomerBE создаётся для представления покупателя или набора покупателей. Если следовать рекомендациям для проектирования OERA, то этот экземпляр должен предоставлять сервисы для различных клиентов.
Объектно-ориентированное программирование на языке ABL поддерживает:
- Наследование
- Инкапсуляцию
- Интерфейсы
- Полиморфизм
Наследование
В объектно-ориентированном программировании классы могут наследовать данные и методы других классов. Это означает, что некоторые или все данные и/или методы суперкласса могут наследоваться производным классом. Производный класс также может иметь собственные данные и методы. В тоже время суперкласс не может наследовать данные или методы производного класса. Наследование способствует повторному использованию кода.
Существует специальный тип суперкласса, который называется абстрактный класс, и который используется в качестве шаблона для ряда производных классов. Вы не можете создавать экземпляры абстрактного класса.
В следующем примере (см. схему ниже) суперклассом является класс Customer, который содержит данные и методы для поддержки покупателя. Вероятно, что приложение должно различать розничных покупателей и оптовых покупателей. И скорее всего для оптовых покупателей необходимы дополнительные данные или функциональность, отличающиеся от тех, которые необходимы для розничных покупателей. В тоже время существуют и общие параметры. Общие описания данных и функциональность могут повторно использоваться, для чего необходимо указать, что классы RetailCustomer и WholesaleCustomer наследуются от суперкласса Customer.
Когда создаётся экземпляр класса RetailCustomer, он содержит значения данных класса Customer, равно как и значения класса RetailCustomer непосредственно. Аналогично методы обоих классов Customer и RetailCustomer доступны для экземпляра RetailCustomer.
Инкапсуляция
Инкапсуляция – это способ ограничить данные и методы, которые доступны пользователям класса. Во время определения класса вы должны указать тип доступа, который каждый элемент данных и метод будут иметь во время выполнения.
Тип доступа |
Описание |
Private | Метод или элемент данных доступен только из методов внутри класса. Методы производного класса не могут получить доступ к таким методам или элементам данных суперкласса. |
Protected | Метод или элемент данных доступен из методов внутри класса или методов производного класса. |
Public | Метод или элемент данных доступен из методов класса или методов производного класса. Доступ также предоставляется любому ABL-коду, который создаёт или использует экземпляр класса. |
Преимущества инкапсуляции:
- Предоставляется только то, что необходимо для взаимодействия с экземпляром класса. Другие части приложения экранированы от (и не должны знать об этом) деталей реализации или изменений.
- Реализация поведения локализована.
- Код просто поддерживать.
Лучше практикой считается скрыть столько данных, насколько это возможно, установив тип доступа элементам данных private или protected. После чего данные класса должны быть доступны только для методов внутри класса.
Интерфейсы
Интерфейс – это ABL-класс, используемый для описания общедоступных элементов данных и методов, которые должны быть реализованы другими классами. Интерфейсный класс не предоставляет код, а просто содержит имена и параметры для методов, которые должны быть реализованы. Интерфейс осуществляет стандарты кодирования для классов, которые реализуют интерфейс. Классы, которые реализуют интерфейс, должны определить и обеспечит код для всех элементов данных и методов, определённых в интерфейсном классе, с идентичными именами, параметрами и возвращаемыми типами. Несколько классов могут реализовать одинаковый интерфейс, чтобы гарантировать стандартизированное поведение.
В качестве примера интерфейсный класс ICusomerInvoice должен определить методы необходимые для реализации функциональности по обработке счетов, например, метод с именем SendInvoice(). Для определения интерфейса ICustomerInvoice определено два класса. Класс RetailCustomerInvoice реализует собственную версию SendInvoice(), которая отправляет счет частным клиентам. А класс EnterpriseCustomerInvoice реализует свою версию SendInvoice(), которая отправляет счёт бизнес-клиентам, используя номер заказа (PO – purchase order).
Полиморфизм
Полиморфизм – это мощная особенность объектно-ориентированного программирования, благодаря которой сокращается количество ABL-кода, который необходимо написать. Чтобы использовать полиморфизм вы должны написать собственные классы с использованием наследования или интерфейсов. Если вы используете наследование, то производные классы должны определять такие же методы как у суперкласса. Интерфейсы уже предоставляют такую возможность, поскольку все реализации интерфейсного класса должны реализовывать одинаковые методы.
Полиморфизм позволяет писать ABL-код так, чтобы получить доступ к экземпляру суперкласса или интерфейсного класс (не волнуясь об особенностях, полученных или реализованных классов или методов), во время выполнения ABL динамически вызывает метод для полученного или реализованного класса.
Приведём пример с интерфейсом. Представьте, что вы определили интерфейсный класс ICustomerInvoice, который определяет, что должен быть реализован метод с именем SendInvoice(). Для реализации ICustomerInvoice вы определили классы RetailCustomerInvoice и EnterpriseCustomerInvoice. Метод SendInvoice() в классе RetailCustomerInvoice использует формат домашнего адреса для отправки счёта частным клиентам. В классе EnterpriseCustomerInvoice метод SendInvoice() использует формат бизнес-адреса с номером заказа (PO) для отправки счёта бизнес-клиентам. Полиморфизм позволяет вам написать код для обработки всех счетов, независимо для кого они предназначены. Написанный вами код вызывает метод SendInvoice() для экземпляра интерфейсного класса ICustomerInvoice, и при этом не должен определять предназначен ли экземпляр для частных или для бизнес клиентов. ABL динамически выберет соответствующий метод для вызова во время выполнения.