Инкапсуляция и расширяемость типов

ООП – это сбалансированный подход к написанию программного обеспечения. Данные и поведение упакованы вместе. Такая инкапсуляция создает определяемые пользователем типы данных, расширяющие собственные типы данных языка и взаимодействующие с ними. Расширяемость типов – это возможность добавлять к языку определяемые пользователем типы данных,которые также легко использовать, как и основные типы.

Абстрактный тип данных, например, строка, является описанием идеального, всем известного поведения типа. Пользователь строки знает, что операции, такие как конкатенация или печать, имеют определенное поведение. Операции конкатенации и печати называются методами.

Конкретная реализация АТД может иметь ограничения; например, строки могут быть ограничены по длине. Эти ограничения влияют на открытое всем поведение. В то же время, внутренние или закрытые детали реализации не влияют прямо на то, как пользователь видит объект. Например, строка часто реализуется как массив; при этом внутренний базовый адрес элементов этого массива и его имя не существенны для пользователя.

Инкапсуляция – это способность скрывать внутренние детали при предоставлении открытого интерфейса к определяемому пользователем типу. В MQL5, как и в C++, для обеспечения инкапсуляции используются определения класса и структуры (class и struct) в сочетании с ключевыми словами доступа private (закрытый), protected (защищенный) и public (открытый).

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

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

Обычно стараются защищать члены класса и объявлять их с модификатором protected, установку и чтение значений этих членов осуществляется с помощью специальныx так называемых set- и get-методов, которые определяются с модификатором доступа public.

Пример:

class CPerson
  {
protected:
   string            m_name;                     // имя
public:
   void              SetName(string n){m_name=n;}// устанавливает имя
   string            GetName(){return (m_name);} // возвращает имя
  };

Такой подход дает несколько преимуществ. Во-первых, по имени функции можно понять что она делает – устанавливает или получает значение члена класса. Во-вторых, возможно в будущем нам понадобится изменить тип переменной m_name в самом классе CPerson или в каком-либо из производных от него классов.

В таком случае нам достаточно будет изменить реализацию функций SetName() и GetName(), сами же объекты класса CPerson можно будет использовать в программе без каких-либо изменений в коде, так как пользователь не будет даже знать,что тип данных m_name изменился.

Пример:

struct Name
  {
   string            first_name;                 // имя
   string            last_name;                  // фамилия
  };
 
class CPerson
  {
protected:
   Name              m_name;                     // имя
public:
   void              SetName(string n);
   string            GetName(){return(m_name.first_name+" "+m_name.last_name);}
private:
   string            GetFirstName(string full_name);
   string            GetLastName(string full_name);
  };
 
void CPerson::SetName(string n)
  {
   m_name.first_name=GetFirstName(n);
   m_name.last_name=GetLastName(n);
  }
 
string CPerson::GetFirstName(string full_name)
  {
   int pos=StringFind(full_name," ");
   if(pos>0) 
      StringSetCharacter(full_name,pos,0);
   return(full_name);
  }
 
string CPerson::GetLastName(string full_name)
  {
   string ret_string;
   int pos=StringFind(full_name," ");
   if(pos>0) 
      ret_string=StringSubstr(full_name,pos+1);
   else      
      ret_string=full_name;
//---
   return(ret_string);
  }

Смотри также

Типы данных