Member Access Rights and Encapsulation
Restricting member access to certain parts of code.
Member Access Rights
Overview
All members of a Type - including member data, procedures, constants, etc. - belong in one of three different classifications, each with its own rules dictating where in code they may be accessed, or referred to.
These rules are called access rights.
There are public, protected and private members, and they are declared in a Type definition following a Public, Protected or Private label, respectively.
By default, that is, without an access classification label, members of a Type are public.
Public membersThese rules are called access rights.
There are public, protected and private members, and they are declared in a Type definition following a Public, Protected or Private label, respectively.
By default, that is, without an access classification label, members of a Type are public.
Public members can be referred to from anywhere; they are accessible from, for example, member procedures or module-level code or procedures.
Protected members
Protected members can only be accessed from member procedures of the Type they are declared in, or member procedures of a derived Type. They are not accessible to outside code.
Private members
Private members can only be accessed from member procedures of the Type they are declared in. They are not accessible to outside code or member procedures from a derived Type.
Constructors and destructors
Constructors and destructors follow the same rules as any other member:
- When public, objects can be instantiated and destroyed from anywhere in code.
- When protected, objects can be instantiated and destroyed only from member procedures of their Type or a derived Type.
- Private constructors and destructors restrict object instantiation solely to member procedures of their Type.
- When protected, objects can be instantiated and destroyed only from member procedures of their Type or a derived Type.
- Private constructors and destructors restrict object instantiation solely to member procedures of their Type.
Encapsulation
Overview
Encapsulation is the process of keeping the details about how an object is implemented hidden away from users of the object.
Instead, users of the object access the object through a public interface.
In this way, users are able to use the object without having to understand how it is implemented.
Encapsulation is implemented via access specifiers (Private, Protected or Public).
Typically, all member variables of the Type are made private (hiding the implementation details), and most member procedures are made public (exposing an interface for the user).
Although requiring users of the Type to use the public interface may seem more burdensome than providing public access to the member variables directly, doing so actually provides a large number of useful benefits that help encourage Type re-usability and maintainability.
Benefit of encapsulated TypesInstead, users of the object access the object through a public interface.
In this way, users are able to use the object without having to understand how it is implemented.
Encapsulation is implemented via access specifiers (Private, Protected or Public).
Typically, all member variables of the Type are made private (hiding the implementation details), and most member procedures are made public (exposing an interface for the user).
Although requiring users of the Type to use the public interface may seem more burdensome than providing public access to the member variables directly, doing so actually provides a large number of useful benefits that help encourage Type re-usability and maintainability.
Protection:
Global access to variables is dangerous because you don’t have strict control over who has access to the global variable, or how they use it.
Only the public members of a Type suffers from the same problem, but just on a smaller scale.
Encapsulation allows the programmer of a Type to:
Abstraction:Only the public members of a Type suffers from the same problem, but just on a smaller scale.
Encapsulation allows the programmer of a Type to:
- Actively control the access to its internals (pointers, variables, ...), by: none / read only / write only / read & write.
- Secure operations, by denying certain destructive user actions (like pointer overwriting, deallocating, ...)
- Secure operations, by denying certain destructive user actions (like pointer overwriting, deallocating, ...)
With a fully encapsulated Type, you only need to know what member procedures are publicly available to use the Type, what arguments they take, and what values they return. It doesn’t matter how the Type was implemented internally.
For example, a Type holding a list of names could have been implemented using different data structures.
In order to use the Type, you don’t need to know (or care) which.
This dramatically reduces the complexity of your programs, and also reduces mistakes.
Hiding the internal implementation details:
More than any other reason, this is the key advantage of encapsulation.
For example, a Type holding a list of names could have been implemented using different data structures.
In order to use the Type, you don’t need to know (or care) which.
This dramatically reduces the complexity of your programs, and also reduces mistakes.
Hiding the internal implementation details:
- internal members declared as Private/Protected and user interface using methods and properties as getter/setter,
- in addition to define constructors, copy-constructor, destructor, assignment operators, ... ,
provides some abstraction.- in addition to define constructors, copy-constructor, destructor, assignment operators, ... ,
More than any other reason, this is the key advantage of encapsulation.
Examples
- In the example below, the data member hour, minute, and second are private while the member procedures set_Time(), get_Time() and increment_Time() are public:
- For a more advanced example using OOP (with encapsulation + abstraction + inheritance + polymorphism), see the example (Graph type collection) in 'Inheritance Polymorphism'.
- As all data is declared as private, the data is only accessible through the public procedures provided by the Type.
- This also allows programmers to validate changes to data members before making such a change. In this example, the set_Time() procedure would be written to check to valid values for time (hour between 0 and 23, minute and second between 0 and 59).
Example of use:
- This also allows programmers to validate changes to data members before making such a change. In this example, the set_Time() procedure would be written to check to valid values for time (hour between 0 and 23, minute and second between 0 and 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
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
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)
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 <> ""
See also:
Back to Programmer's Guide