Lesson 2 - First object-oriented application in VB - Hello object world
In the previous lesson, Introduction to object-oriented programming in VB.NET, we introduced the object-oriented programming and went over what makes it more efficient than any other programming methodology. We already know that objects have fields and methods. We also know that to create an object we'd have to create a class first. Remember that a class is a pattern according to which we create instances later.
As we did in the Basic constructs of VB.NET course we'll create what must always be done when you encounter a new paradigm in programming, a "Hello World" program. A Hello object world program, to be precise!
We'll start by creating a new Visual Studio console application. In the Solution Explorer, on the right, right-click on your project and select Add -> Class. You can also use the Shift + Alt + C shortcut.
We'll name our class Greeter.vb and confirm. We name classes using CamelCase, meaning that the first letter in every word in the class name is capitalized and we don't write spaces. The name, of course, shouldn't contain any accent characters, if your native language uses any, you can use them in strings, but never in identifiers.
We're going to create a "greeter" object using this class later, which will be able to greet the user. You might've noticed by now that we're treating the program in a different way, for every action, there is some object responsible. One should not simply start by writing stuff into the Main() method. In our case, it may seem useless, but in more complex applications it'll prove to be more than worthwhile
Another .vb file will be added to our Solution Explorer and VS will open it for us. We can later return to the original Module1.vb with the Main() method using tabs or via the Solution Explorer.
Let's take a look at what VS has generated for us and add a greeting method to the class.
Public Class Greeter End Class
Public Class declares a new class. Since we want it to be visible from the Module1.vb file as well, we need to declare it as Public.
Notice that the code is almost the same as in Module1.vb, except there it was a module which is very similar to a class. We now understand what we looked over in the previous course. Our console program was actually a class containing the Main() method. You see, in Visual Basic, there is no real way of creating "non-OOP programs", which is a good thing
Next, we'll add a Greet() method to the Greeter class, which will be publicly visible and won't return a value or take any parameters.
In Visual Basic .NET, we declare methods as follows:
[Access modifier] Sub [MethodName]
We'll write an access modifier before the method, which in our case is Public. If we omit the modifier, VB.NET will assume it is a Private, non-public, method. To make the method not return a value we must declare the method using the Sub keyword. Followed by the method's name, which we will write in CamelCase as well. We'll show how to declare parametrized methods as well later.
In the method body, we'll write code that prints a message to the console.
Our class will now look like this:
Public Class Greeter Public Sub Greet() Console.WriteLine("Hello object world!") End Sub End Class
That's all we'll do for the class for now. Let's move on to Module1.vb.
We'll create an instance of the Greeter class in the Main() method body. Which will be a greeter object that we'll be able to work with. We store objects in variables and use the class name as the data type. Instances usually have the same name as classes, but with the first character in lowercase. Let's declare the variable and then store a new Greeter class instance within it:
Dim greeter As Greeter greeter = New Greeter()
The first line says: "I want a variable named "greeter" that will later contain a Greeter instance". We've already worked with the variables like this.
The second line contains the New keyword which will create a new Greeter class instance. We assign this instance to our variable.
When a new instance is created, the constructor is called. The constructor is a special class method, that's why we write the empty parentheses when creating an instance, we're calling this "creation" method. The constructor usually contains some initialization of the object's internal state, e.g. it initializes the fields with default values. We haven't declared a constructor in our class, that's why VB.NET created the implicit parameterless constructor. So creating an instance of an object is similar to calling a method. Of course, the entire code can be shortened to:
Dim greeter As Greeter = New Greeter()
Since now we have a Greeter class instance in a variable, we can let it greet
the user. We'll call the Greet() method as
greeter.Greet()
. We will also add Console.ReadKey()
into the application. The Main() method code will now look like this:
{VBNET_OOP}
Public Class Greeter
Public Sub Greet()
Console.WriteLine("Hello object world!")
End Sub
End Class
{VBNET_MAIN_BLOCK}
Dim greeter As Greeter = New Greeter()
greeter.Greet()
Console.ReadKey()
{/VBNET_MAIN_BLOCK}
{/VBNET_OOP}
Let's run the program:
Your first object-oriented app
Hello object world!
You can run the program in our online compiler as well, just notice that all classes are in the same file there if you click on the code. It's simpler for our online samples, however, you keep classes in separated files in your projects. We have successfully made our first object-oriented app!
Now let's add a name parameter to our Greet() method, so it could greet the user properly:
Public Sub Greet(name As String) Console.WriteLine("Hi {0}", name) End Sub
The syntax of the method parameter is the same as the syntax of a variable, we just omit the Dim keyword. If we wanted more parameters, we'd separate them with commas. Let's modify our Main() method now:
{VBNET_OOP}
Public Class Greeter
Public Sub Greet(name As String)
Console.WriteLine("Hi {0}", name)
End Sub
End Class
{VBNET_MAIN_BLOCK}
Dim greeter As Greeter = New Greeter()
greeter.Greet("Carl")
greeter.Greet("Peter")
Console.ReadKey()
{/VBNET_MAIN_BLOCK}
{/VBNET_OOP}
Our code is now in a method and we're able to call it multiple times with
different parameters. We don't have to copy "Hi ..."
twice. We'll
separate our code logically into methods from now.
Console application
Hi Carl
Hi Peter
Let's add some field (attribute) to the class, e.g. a text where the greeting will be stored. We declare fields as variables as well. We will also write an access modifier before them just like before otherwise VB.NET would assume that they're Private. Here's what your class should look like at this point:
Public Class Greeter Public text As String Public Sub Greet(name As String) Console.WriteLine("{0} {1}", text, name) End Sub End Class
We have to initialize the text in the instance created in Module1.vb:
{VBNET_OOP}
Public Class Greeter
Public text As String
Public Sub Greet(name As String)
Console.WriteLine("{0} {1}", text, name)
End Sub
End Class
{VBNET_MAIN_BLOCK}
Dim greeter As Greeter = New Greeter()
greeter.text = "Hi"
greeter.Greet("Carl")
greeter.Greet("Peter")
greeter.text = "Hello programmer"
greeter.Greet("Richard")
Console.ReadKey()
{/VBNET_MAIN_BLOCK}
{/VBNET_OOP}
Console application
Hi Carl
Hi Peter
Hello programmer Richard
In object-oriented design, it's not recommended to let each object control
the input and output, i.e. printing lots of stuff into the console. Each object
should have a single responsibility and shouldn't exceed its purpose. Let's make
our object solely responsible for creating the greeting text, and we'll move the
printing outside the object, i.e. to the main()
method. The
advantage to designing objects with a single responsibility is that they're then
universal and reusable. Our object can only print text to the console now, but
we'll change it so the method will only return the text and it'll be up to the
recipient to decide what to do with it. Like this we could store greetings into
files, print them on websites or process them further.
Since we want the method to return a String value, we'll change the Sub keyword to the Function and we specify the return value type. We use the Return keyword to return a value. The Return keyword terminates the method and returns the value. Any code in the method's body after the Return will not be executed! Let's modify both classes:
The Greet() method in Greeter.vb:
Public Function Greet(name As String) As String Return String.Format("{0} {1}", text, name) End Function
The Main() method body in Module1.vb:
{VBNET_OOP}
Public Class Greeter
Public text As String
Public Function Greet(name As String) As String
Return String.Format("{0} {1}", text, name)
End Function
End Class
{VBNET_MAIN_BLOCK}
Dim greeter As Greeter = New Greeter()
greeter.text = "Hi"
Console.WriteLine(greeter.Greet("Carl"))
Console.WriteLine(greeter.Greet("Peter"))
greeter.text = "Hello programmer"
Console.WriteLine(greeter.Greet("Richard"))
Console.ReadKey()
{/VBNET_MAIN_BLOCK}
{/VBNET_OOP}
Now, our code follows the guidelines of good OOP and over all programming practices. We will also add comments in our class accordingly. We'll add comments over the class name and over the name of each field and method. We'll use the triple apostrophe to write comments ''', VS will then generate an XML, where we'll describe everything that's happening. Comments are useful when we make new class methods because its description will then be available to us in IntelliSense. We can collapse them comments by using small "-" buttons, if needed. A fully documented class might look something like this:
''' <summary> ''' A class represents a greeter whose purpose is to greet the user ''' </summary> Public Class Greeter ''' <summary> ''' Greeting text ''' </summary> Public text As String ''' <summary> ''' Greets the user with the stored greeting and his/her name ''' </summary> ''' <param name="name">The user's name</param> ''' <returns>The greeting text</returns> Public Function Greet(name As String) As String Return String.Format("{0} {1}", text, name) End Function End Class
Let's check and see if VS actually displays descriptions we've set in IntelliSense:
Great! Our program already has some quality to it, despite it being relatively useless. If you want, you can try to create an object-oriented remake of our console calculator. In the next lesson, Solved tasks for OOP in VB .NET lesson 1-2, we'll program a simple game. We'll make two objects, warriors, compete in an arena, which will also be an object. See? Now you have something to look forward to!
In the following exercise, Solved tasks for OOP in VB .NET lesson 1-2, we're gonna practice our knowledge from previous lessons.