Virtual Developer Workshop: Containerized Development with Docker
Visual Basic is quite easy. It gets a lot of flack for being so easy. It makes learning the concepts of programming very simple. I used to be a programming trainer and used the BASIC language as the first stepping stone into the world of software development, and it has worked. It has worked for me, technically.
Let me tell you the boring story: I finished school back in 1996. By that time, my parents had already started a computer college. Needless to say, things were a lot different then. I didn't want to be involved, honestly. Not having many other qualifications basically forced me into it. A few years on, I decided to venture into programming. I attempted to start with Visual C++.
It was horrible. I struggled. Add to that the fact that the book I used was literally full of errors and I had to find the errata online (with dial-up Internet). If it wasn't for Codeguru, I would have ended up somewhere else.
I persisted, even though I had no idea what I was doing. I bought a book about Visual Basic. The language just made it simple enough for me to understand what I was doing. Only after I fully grasped Visual Basic, I could venture back to Visual C++ and understand it better. The funny part is that now I am employed as a C# developer.
Enough about me. The aim of this article is not to bore you; it is to dig into some of the intricacies of Visual Basic. Today you will learn about Scope, Modules, and Accessibility Modifiers in Visual Basic.
Scope, in programming terms, refers to the visibility of assets. These assets include variables, arrays, functions, classes, and structures. Visibility in this case means which parts of your program can see or use it.
Essentially, there are four levels of scope in Visual Basic. These are:
- Block scope: Available only within the code block in which it is declared
- Procedure scope: Available to all code within the procedure in which it is declared
- Module scope: Available to all code within the module, class, or structure in which it is declared
- Namespace scope: Available to all code in the namespace in which it is declared
A block is a set of statements enclosed within starting and ending declaration statements, such as the following:
- If and End If
- Select and End Select
- Do and Loop
- While and End While
- For [Each] and Next
- Try and End Try
- With and End With
If you declare a variable within a block, such as the above-mentioned examples, you can use it only within that block. In the following example, the scope of the SubTotal variable is the block between the If and End If statements. Because the variable SubTotal has been declared inside the block, you cannot refer to SubTotal when execution passes out of the block.
If Tax > 15.0 Then Dim SubTotal As Decimal SubTotal = Tax * SubTotal 'Correct' End If 'Wrong. Will Not Work Because SubTotal is Out of Scope!' MessageBox.Show(SubTotal.ToString())
Procedure scope refers to an an element that is declared within a procedure is not available outside that procedure. Only the procedure that contains the declaration can use it. Variables at this level are usually known as local variables.
In the following example, the variable strWelcome declared in the ShowWelcome Sub procedure cannot be accessed in the Main Sub procedure:
Sub Main() ShowWelcome() Console.WriteLine(strWelcome) 'Will not work!' Console.WriteLine("Press Enter to continue...") Console.ReadLine() End Sub Sub ShowWelcome()] Dim strWelcome = "Hello friend" Console.WriteLine(strWelcome) End Sub
You can declare elements at the Module level by placing the declaration statement outside of any procedure or block but within the module, class, or structure. When you create a variable at module level, the access level you choose determines the scope. More on Access Modifiers later.
Private elements are available to every procedure in that particular module, but not to any code in a different module.
In the following example, all procedures defined in the module can refer to the string variable strWelcome. When the second procedure is called, it displays the contents of the string variable strWelcome in a messagebox.
Private strWelcome As String 'Outside of all Procedures' Sub StoreWelcomeGreeting() strWelcome = "Welcome to the world of Programming" End Sub Sub SayWelcome() MessageBox.Show(strWelcome) End Sub
Namespace scope can be thought of as project scope. By declaring an element at module level using either the Friend or Public keyword, it becomes available to all procedures throughout the namespace in which the element is declared. An element available from within a certain namespace also is available from within any namespaces that are nested inside that namespace. Public elements in a class, module, or structure are available to any project that references their project, as well.
If I had changed the declaration of strWelcome (from the previous example) to:
Public strWelcome As String 'Outside of all Procedures'
strWelcome would have been accessible throughout the entire namespace.
A module is simply a type whose members are implicitly Shared and scoped to the declaration space of the standard module's containing namespace. This means that the entire Namespace can access items in the Module.
Fully Qualified Names
A fully qualified name is an unambiguous name that specifies which function, object, or variable is being referred to. An object's name is fully qualified when it includes all names in the hierarchic sequence above the given element as well as the name of the given element itself.
Members of a standard module essentially have two fully qualified names if:
- One fully qualified name is the name without the standard module name in front.
- One fully qualified name is one including the standard module name.
More than one module in a namespace may contain a member with the same name. Unqualified references to it outside of either module are ambiguous. For example:
Namespace Namespace1 Module Module1 Sub Sub1() End Sub Sub Sub2() End Sub End Module Module Module2 Sub Sub2() End Sub End Module Module Module3 Sub Main() Sub1() 'Valid - Calls Namespace1.Module1.Sub1' 'Valid - Calls Namespace1.Module1.Sub1' Namespace1.Sub1() Sub2() 'Not valid - ambiguous' Namespace1.Sub2() 'Not valid - ambiguous' 'Valid - Calls Namespace1.Module2.Sub2' Namespace1.Module2.Sub2() End Sub End Module End Namespace
Differences Between Modules and Classes
The main difference between Modules and Classes is in the way they store data.
There is never more than one copy of a module's data in memory. This means that when one part of your program changes a public object or variable in a module, and another part subsequently reads that variable, it will get the same value. Classes, on the other hand, exist separately for each instance of the class—for each object created from the class.
Another difference is that data in a module has program scope. This means that the data exists for the entire life of your program; however, class data for each instance of a class exists only for the lifetime of the object.
The last difference is that variables declared as Public in a module are visible from absolutely anywhere in the project, whereas Public variables in a class can only be accessed if you have an object variable containing a reference to a particular instance of a class.
The access level of an object is what code has permission to read it or write to it. This level is determined not only by how you declare the object itself, but also by the access level of the object's container. The keywords that specify access level are called access modifiers. Visual Basic includes five (5) Access Levels, and they are:
- Protected Friend
Public indicates that the objects, functions, and variables can be accessed from code anywhere in the same project, or from outside projects that reference the project, and from any assembly built from the project. The next code segment creates a Public Course Class and accesses it from somewhere else in the project:
Public Class Course Public CourseName As String End Class Public Class Student Public Sub Enroll() Dim c As New Course() c.CourseName = "Introduction to Programming" End Sub End Class
Protected indicates that the objects, variables, and functions can be accessed only from within the same class, or from a class derived from this class. A derived class is simply a class that inherits features from another class, which is called the base class.
The following segment shows that if a class is not derived from a base class, it cannot access its members:
Public Class Course Protected Duration As Integer End Class Public Class ProgrammingCourse Inherits Course Public Sub ChooseCourseDuration() Duration = 12 'OK' End Sub End Class Public Class WebDesignCourse Public Sub ChooseCourseDuration() Dim c As New Course() 'Inaccessible Because of Protection Level' c.Duration = 12 End Sub End Class
Friend specifies that the objects, functions, and variables can be accessed from within the same assembly, but not from outside the assembly.
Public Class Course Friend Cost As Double End Class Public Class GraphicDesignCourse Public Sub SetCost() Dim c As New Course() c.Cost = 5000 'OK' End Sub End Class
Public Class BasicCourse Public Sub SetCost() Dim c As New Course() 'Cannot Access from external Assembly' c.Cost = 4000 End Sub End Class
Protected Friend specify that objects, functions, and variables can be accessed either from derived (inherited) classes or from within the same assembly, or both.
Private indicates that the objects, variables, and functions can be accessed only from within the same module, class, or structure.
Understanding Scope, Modules, and Access Levels is crucial in building any decent application. The sooner you know these, the better.