The notion of accessibility (or scope) in class modules is more involved than it is in standard modules. As far as local variables (block-level and procedure-level) are concerned, there is no difference — we have block scope and procedure-level scope.
(For standard modules, only
Actually, we can dispense with the
Friend modifier in one statement:
Friend is equivalent
another way, if
Protected sets a specific range of
accessibility (or inheritance — see below) and
Friend sets a different range, then
accessibility to the union of those
ranges — if a member falls into either
range, it passes the accessibility (or inheritance) criterion.
Note that class modules themselves can be declared with any one of
the three access modifiers:
Protected is not allowed). When a class module
declaration specifies one of these access modifiers, this simply
restricts all of its members to that level of access, unless a
member’s access is further restricted by the access
modifier on the member declaration itself. For instance, if the class
Friend access, no member can have
Public access. (Put another way, the
Public access is overridden by the
Friend class access.)
On the other hand, all four access modifiers apply to members of the class module — that is, to variable, constant, enum, and procedure declarations within the class module.
To avoid confusion in discussing the access modifiers, it helps to separate the issue of accessibility of members from that of inheritance of members.
Public Class Class1 Public pub As Integer = 1 Private priv As Integer = 1 Protected p As Integer = 1 Friend f As Integer = 1 Protected Friend pf As Integer = 1 End Class Public Class Class1Derived Inherits Class1 Public Sub test( ) ' Not allowed - private members are not inherited Me.priv = 4 ' Allowed only in derived classes in the same project as base class Me.f = 4 ' Allowed in all derived classes Me.pub = 4 Me.p = 4 Me.fp = 4 End Sub End Class
Note that the Me. syntax is optional, and we could write, for instance, simply:
pub = 4 p = 4 f = 4 fp = 4
The fact that the code:
Me.p = 4
is valid in Class1Derived means that this class has inherited the member p. In other words, an object of class Class1Derived has a member variable named p. The fact that:
fails to work in Class1Derived if Class1Derived is in a different project than Class1 means that such classes do not inherit the member f.
Private members are never inherited.
Public members are inherited by all derived classes.
Protected members are inherited by all derived classes (and therefore so are Protected Friend members).
Friend members are inherited by all derived classes in the same project as the base class only.
Now we come to member accessibility. Unfortunately, the term accessibility is used quite loosely in most documentation, but to make absolutely clear sense of the issue, we must be specific. Many writers simply refer to a member’s accessibility, but this is ambiguous. To illustrate, consider the code:
Public Class Class1 Public x As Integer = 1 End Class Public Class Class2 Inherits Class1 End Class
Now, it makes sense to ask about the accessibility of the Public member x of Class1 or the (inherited) Public member x of Class2. It does not make sense to ask about the accessibility of the member x alone, without mention of the class involved. Indeed, we say that the Public member x of Class1 is accessible from a class Class3 if the following is legal:
Public Class Class3 Public Sub Test( ) Dim c1 As new Class1( ) c1.x = 5 End Sub End Class
On the other hand, the Public member x of class Class2 is accessible from Class3 if we can write:
Public Class Class3 Public Sub Test( ) Dim c2 As new Class2( ) c2.x = 5 End Sub End Class
Let m be a Protected member of ClassA. Then from any subclass ClassB of ClassA, we can access the member m of ClassB or the member m of any subclass of ClassB. Another way to phrase this is as follows. Let m be declared as Protected in a class ClassA. Let Class B be a subclass of ClassA. Then the member m of ClassB is accessible in each class between ClassB and ClassA in the inheritance hierarchy.
Clearly, the definition of
Protectedneeds clarification. To do so, consider a chain of derived classes (that is, ClassN+1 is derived from ClassN):
Class1 Class2 . . . ClassA ' This is the first appearance of the protected method MyMethod ' Thus, all classes below inherit MyMethod Protected Sub MyMethod( ) . . . ClassB ' ClassB can call MyMethod because it has been inherited ' This is accessibility of MyMethod for ClassB MyMethod( ) ' Note that this is equivalent to Me.MyMethod( ) ' Can access MyMethod for any Class at or below this class ' For example, the following are legal: Dim b As New ClassB b.MyMethod( ) Dim c As New ClassC c.MyMethod( ) ' But the following is not legal Dim a As New ClassA a.MyMethod( ) . . . ClassC ' Can access MyMethod for any Class at or below this class ' For example, the following are legal: Me.MyMethod( ) Dim c As New ClassC c.MyMethod( ) Dim d As New ClassD d.MyMethod( ) ' But the following is not legal Dim b As New ClassB b.MyMethod( ) . . . ClassD . . . ClassN
As you can see, the rules for Protected mode access are a bit involved. Actually, Protected mode should be used with some care. For instance, declaring a member variable Protected violates one of the principal rules of good object-oriented programming, encapsulation, as does declaring the member Public. Thus, it should be done only if you are certain that derived classes will be well behaved (or are willing to accept the risk). The same applies to Protected methods.