型の封裝と拡張

OOP はソフトウェアを書くのにバランスのとれたアプローチです。データと操作演算は一体化されています。このカプセル化は、ユーザ定義のデータ型を作成し、言語データ型を拡張しそれらと相呼応します。型の拡張は言語に使いやすいユーザ定義のデータ型、ならびに基本型を追加する機会です。

例えば抽象データ型の文字列は、理想的なよく知られた操作演算の種類を描画します。

文字列のユーザは、連結やプリントなどの文字列操作が特定の動作を持っていることを知っています。このような操作はメソッドと呼ばれます。

ADT の特定の実装は、例えば、文字列の長さの制限などを有することがあります。これらの制限は全ての操作演算に影響を与えます。同時に、内部またはプライベート実装の詳細はユーザがオブジェクトを見る方法には直接影響しません。例えば、文字列は多くの場合配列として実装されていて、配列の内部ベースアドレスや名称はユーザには必要でありません。

カプセル化はユーザ定義型へのオープンインタフェースが提供された時に実装の詳細を隠す機能です。MQL5 言語ではクラスと構造体の定義(classstruct )は privateprotected 及び public のアクセスキーワードとともにカプセル化の規定に使用されています。

public キーワードは、キーワードの使用されたメンバへのアクセスが制限なくオープンなことを示します。このキーワードが指定されなかった場合、クラスメンバは、デフォルトでロックされています。private メンバは、そのクラスのメンバ関数のみからアクセス出来ます。

Protected クラス関数はこのクラスでだけでなくその継承クラスからも利用可能です。Public クラス関数は、クラス宣言の有効範囲内の全ての関数から利用可能です。この様な保護は、クラスの実装の一部を隠してデータの構造の予期しない変更を防止します。アクセス制限やデータ隠蔽はオブジェクト指向プログラミングの特徴です。

通常、クラス関数は保護されており protected 修飾子を使用して宣言されます。値の読み書きは public 修飾子を用いて定義された特殊ないわゆるセットメソッドとゲットメソッドを用いて行われます。

 

例:

class CPerson
 {
protected:
  string            m_name;                     // 名称
public:
  void              SetName(string n){m_name=n;}// 名称を付ける
  string            GetName(){return (m_name);} // 名称を返す
 };

 

このアプローチにはいくつかの利点があります。まず、関数名で関数の機能がわかります。つまりクラスメンバの値をセットまたはゲットするものです。次に、将来的に CPerson クラスまたはその派生クラスのいずれかで m_name 変数の型を変更する必要があるかもしれません。

この場合必要なのは SetName() と GetName() 関数の実装の変更だけです。 m_name のデータ型の変更はユーザに知られる余地もなく、CPerson クラスのオブジェクトはコード変更なしでプログラムで使用できます。

例:

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);
 }

参照

データ型