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.
However, members of a class module can be assigned one of the following access modifiers:
(For standard modules, only Public
,
Private
, and Friend
are
allowed.)
Actually, we can dispense with the Protected
Friend
modifier in one statement:
Protected
Friend
is equivalent
to Protected
or Friend
. Put
another way, if Protected
sets a specific range of
accessibility (or inheritance — see below) and
Friend
sets a different range, then
Protected
Friend
sets
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: Public
,
Private
, or Friend
(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
has 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.
Let us first address member inheritance. Suppose that a class named Class1 has a derived class named Class1Derived, as shown in the following:
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:
Me.f
fails to work in Class1Derived if Class1Derived is in a different project than Class1 means that such classes do not inherit the member f.
Now, the rules of inheritance are:
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
With this in mind, we can describe the accessibility rules clearly:
-
Private
If ClassA is a class with a Private member m, we cannot access the member m of ClassA from any other class.
-
Public
If ClassA is a class with a Public member m, we can access the member m of ClassA from any other class.
-
Friend
If ClassA is a class with a Friend member m, we can access the member m of ClassA from any other class that is in the same project as ClassA.
-
Protected
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
Protected
needs 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.
Get VB.NET Language in a Nutshell, Second Edition now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.