コードのある部分への、メンバーアクセスを制限します。
メンバーアクセス権
概要
Type のすべてのメンバー(メンバーデータ、手続き、定数など)は、3つの異なる分類のいずれかに属します。それぞれ、コード上のどこでアクセスしたり、参照したりできるかを決定する独自のルールを持っています。
これらのルールをアクセス権と呼びます。
メンバーには 公開(public)、保護(protected)、個人(private) があり、それぞれ
Public,
Protected,
Private のラベルに続く
Type の定義で宣言されます。
デフォルト、つまり、アクセス分類ラベルがない場合、
Type のメンバーは公開(public)です。
公開のメンバー
公開のメンバーは、どこからでも参照できます。
公開のメンバーは、例えば、メンバー手続きや、モジュール・レベルのコードまたは手続きから、アクセスできます。
保護されたメンバー
保護されたメンバーは、メンバーが宣言される、
Type のメンバー手続き、または生成された
Type のメンバー手続きから、アクセスできるだけです。
保護されたメンバーは、コードの外にアクセスできません。
個人メンバー
非公開のメンバーは、ただ、メンバーが宣言された、
Type のメンバー手続きから、アクセスできるだけです。
非公開のメンバーは、外部のコードに、アクセスできません。また、生成された
Type から、メンバー手続きに、アクセスできません。
構築子と解体子
構築子と解体子は、他のいかなるメンバーとも同じ規則に従います:
- public の場合、オブジェクトはコード上のどこからでもインスタンス化と破棄が可能です。
- 保護されている場合、オブジェクトは、その
Type または派生
Type のメンバ手続きからのみインスタンス化と破棄が可能です。
- プライベートの構築子と解体子は、オブジェクトのインスタンス化をその
Type のメンバ手続きにのみ制限します。
カプセル化
概要
カプセル化とは、あるオブジェクトがどのように実装されているかの詳細を、そのオブジェクトのユーザーから隠しておくプロセスです。
代わりに、オブジェクトのユーザーはパブリック・インターフェイスを通してオブジェクトにアクセスします。
このようにして、ユーザーはオブジェクトがどのように実装されているかを理解しなくても、オブジェクトを使うことができます。
カプセル化は、アクセス指定子(Private、Protected、Public)によって実装されます。
通常、
Type のすべてのメンバ変数は Private(実装の詳細を隠す)とされ、ほとんどのメンバ手続きは Public(ユーザにインターフェースを公開)とされます。
Type のユーザにパブリック・インターフェースの使用を要求することは、メンバ変数に直接パブリック・アクセスを提供するよりも負担が大きいように見えるかもしれませんが、実際にはそうすることで
Type の再利用性と保守性を促進する多くの有用な利点が得られます。
カプセル化された型の利点
保護:
変数へのグローバル・アクセスは、誰がグローバル変数にアクセスできるか、またどのように使うかを厳密にコントロールできないため、危険です。
Type のパブリック・メンバーだけが同じ問題を抱えていますが、その規模は小さいものです。
カプセル化によって、
Type のプログラマーは以下のことが可能になります:
- 型の内部(ポインタや変数など)へのアクセスを積極的に制御することができます(none / read only / write only / read & write)。
- ある種の破壊的なユーザアクション(ポインタの上書き、デアロケートなど)を拒否することで、操作を安全にします。
抽象化:
完全にカプセル化された
Type では、その
Type を使うためにどのようなメンバー手続きが公開されているか、それらがどのような引数を取り、どのような値を返すかを知っているだけでよいのです。
Type が内部でどのように実装されているかは問題ではありません。
例えば、名前のリストを保持する
Type は、異なるデータ構造を使って実装することができました。
しかし、その
Type を使うためには、どのデータ構造を使っているかを知る必要はありません。
これにより、プログラムの複雑さが劇的に軽減され、ミスも減ります。
内部実装の詳細を隠します:
- 内部のメンバーは Private/Protected として宣言され、ユーザー・インターフェースは、メソッドやプロパティをゲッター/セッターとして使います。
- さらに、構築子、コピー構築子、解体子、代入演算子などを定義します。
ある種の抽象化を提供します。
これが何よりもカプセル化の利点です。
例
-
以下の例では、データ・メンバー hour, minute, second は private で、メンバー手続きの set_Time(), get_Time(), increment_Time() は public です:
- すべてのデータが private と宣言されているため、データは
Type が提供する public な手続きを介してのみアクセス可能になります。
- これにより、プログラマーはデータメンバーの変更を行う前に、その変更を検証することができます。
この例では、
set_Time() 手続きは、時間の有効な値 (時:0〜23、分と秒:0〜59) をチェックするように書かれています。
Type my_Time
Public:
Declare Sub set_Time (ByVal new_Hour As UByte, ByVal new_Minute As UByte, ByVal new_Second As UByte)
Declare Sub get_Time (ByRef curr_Hour As UByte, ByRef curr_Minute As UByte, ByRef curr_Second As UByte)
Declare Function get_Time () As String
Declare Sub increment_Time ()
Private:
Dim As UByte Hour
Dim As UByte Minute
Dim As UByte Second
End Type
使用例:
Type my_Time
Public:
Declare Sub set_Time (ByVal new_Hour As UByte, ByVal new_Minute As UByte, ByVal new_Second As UByte)
Declare Sub get_Time (ByRef curr_Hour As UByte, ByRef curr_Minute As UByte, ByRef curr_Second As UByte)
Declare Function get_Time () As String
Declare Sub increment_Time ()
Private:
Dim As UByte Hour
Dim As UByte Minute
Dim As UByte Second
End Type
Sub my_Time.set_Time (ByVal new_Hour As UByte, ByVal new_Minute As UByte, ByVal new_Second As UByte)
If new_Hour <= 23 And new_Minute <= 59 And New_Second <= 59 Then
This.Hour = new_Hour
This.Minute = new_Minute
This.Second = new_Second
End If
End Sub
Sub my_Time.get_Time (ByRef curr_Hour As UByte, ByRef curr_Minute As UByte, ByRef curr_Second As UByte)
curr_Hour = This.Hour
curr_Minute = This.Minute
curr_Second = This.Second
End Sub
Function my_Time.get_Time () As String
Return Right("0" & Str(This.Hour), 2) & ":" & Right("0" & Str(This.Minute), 2) & ":" & Right("0" & Str(This.Second), 2)
End Function
Sub my_Time.increment_Time ()
This.Second += 1
If This.Second = 60 Then
This.Second = 0
This.Minute += 1
If This.Minute = 60 Then
This.Minute = 0
This.Hour += 1
If This.Hour = 24 Then
This.Hour = 0
End If
End If
End If
End Sub
Dim As my_Time my_T
Dim As UByte h, m, s
Input "Hour? ", h
Input "Minute? ", m
Input "Second? ", s
my_T.set_Time(h, m, s)
Print
Dim As Double Tr = Int(Timer)
Do
If Tr <> Int(Timer) Then
Tr = Int(Timer)
my_T.increment_Time()
Locate , 1, 0
Print my_T.get_Time;
End If
Sleep 100, 1
Loop Until Inkey <> ""
Print
- OOP を使ったより高度な例(カプセル化+抽象化+継承+ポリモーフィズムを使う)は、継承ポリモーフィズム の例(グラフ型コレクション)を参照してください。
参照: