The Benefits of OOP
Have you wondered why modern programming languages tend to be object-oriented? C++ was created as an extension of C to support OOP. And Java, one of the most popular languages on the planet, is also an OOP language. Then, of course, VisualBasic has evolved into VB.NET, a fully OOP language. There is a good reason for this transformation. OOP offers several benefits, such as easy code maintenance, extensibility, and code reuse, not found in procedural programming languages. Some of the benefits are outlined below.- Easy Maintenance. Modularity is inherent in OOP. Entities are represented by classes and classes with the same functionality are located in the same namespace (package). You can add a class into a namespace without affecting other members of the namespace.
- Extensibility. OOP naturally supports extensibility. Having a class with certain functionality, you can quickly extend that class to create a different class with extended functionality.
- Code Reuse.Since functionality is encapsulated into a class and each class is an independent entity, providing a library is very easy. In fact, programmers of any .NET Framework language can and should use the .NET Framework class library, an extensive library that provides rich functionality. Better still, you can extend the functionality of the class library to provide classes that suit your needs.
OOP Features
Now, let's look at some of the features of OOP, starting with the easiest one, classes.Classes
Classes are the main focus in OOP. Simply put, a class is a data type that provides some functionality. A class in VB.NET is declared using the keywordClass
. For example, Listing 1 presents a class called Employee
.Listing 1: Class Employee
Class Employee
End Class
As simple as that. Note that Microsoft recommends the use of Pascal-case naming for classes. This means the first character of a class name is uppercase, and so is the first letter of any subsequent concatenated words. Good class names according to this convention include GeneralManager
, SmallDictionary
, StringUtil
, and so on. Class Members
Work
.Listing 2: Class Employee with method Work
Class Employee
Public Sub Work ()
' Do something here
End Sub
End Class
Subroutines and functions are both called methods. Method names are also Pascal-case. Another type of class member is a field. A field name is camel-case, which means you capitalize the first character of each word except the initial character. Examples of good field names are salary
, quarterlyBonus
, etc. Adding two fields called salary
and yearlyBonus
to the Employee
class in Listing 2 will result in the following code. Listing 3: Class Employee with two fields
Class Employee
Dim salary As Decimal = 40000
Dim yearlyBonus As Decimal = 4000
Public Sub PrintSalary()
' print the salary to the Console
System.Console.Write(salary)
End Sub
End Class
Instantiating an Object
A class is a template or a blueprint of the entity that the class represents. To use a class's field or method or any other member, you need to first turn the class into an object, just as the blueprint of a sports car is useless until assembly workers make the car. In other words, you drive a car, not the blueprint of a car.In OOP, an object is said to be an instance of a class. Creating an object is therefore known as instantiation. The code in Listing 4 demonstrates the instantiation of the
Employee
class. Listing 4: Instantiating an object
Class Employee
Dim salary As Decimal = 40000
Dim yearlyBonus As Decimal = 4000
Public Sub PrintSalary()
' print the salary to the Console
System.Console.Write(salary)
End Sub
End Class
Module Module1
Public Sub Main()
Dim anEmployee As Employee
anEmployee = New Employee()
anEmployee.PrintSalary()
End Sub
End Module
The module Module1
in Listing 4 provides the Main
sub, which is the entry point of a VB.NET program. In order to compile, a source file must provide access to the Main
sub in one way or another. If you are not using Visual Studio.NET, you can compile your VB.NET program with vbc.exe, which is automatically installed when you install the .NET Framework. For instance, if you save your source code as Employee.vb, go to the directory where the file Employee.vb is stored, and then type vbc Employee.vb
. Now back to the code. The
Main
sub first declares an object variable of type Employee
. The variable is called anEmployee
.
Dim anEmployee As Employee
It then instantiates Employee with the keyword New
.
anEmployee = New Employee()
Now that you have an object of type Employee, you can use its functionality. (Once the car is built, you can start and drive it.) In our example, we can call the PrintSalary
method as follows.
anEmployee.PrintSalary()
This will print the value of the salary
variable in Employee
. You can also move the
Main
sub into the class. This way, you don't need a module. This approach is shown in Listing 5.
Class Employee
Dim salary As Decimal = 40000
Dim yearlyBonus As Decimal = 4000
Public Sub PrintSalary()
' print the salary to the Console
System.Console.Write(salary)
End Sub
Public Shared Sub Main()
Dim employee As Employee
employee = New Employee()
employee.PrintSalary()
End Sub
End Class
Note that
System.Console.Write
in the PrintSalary
method means that you call the Write
method of the Console
class. Console
is part of the System
namespace. Namespaces are discussed next. Namespaces
When you write a .NET program, you write classes and other types. To make your application more organized, you can group your classes into namespaces. This is also what Microsoft does with the .NET Framework class library. If you open the .NET Framework class library in the .NET Framework SDK documentation, you can see there are more than 80 namespaces. Important namespaces you will frequently use includeSystem
, System.IO
, System.Drawing
, System.Windows.Forms
, etc. For example, in the
PrintSalary
method in the Employee
class we used the Console
class in the System
namespace. If you will be using a namespace often, you can import a namespace so that you don't have to repeat it every time you want to use its member. For instance, you can rewrite the code in Listings 4 and 5 as shown below.
Listing 6: Importing a namespace
Imports System
Class Employee
Dim salary As Decimal = 40000
Dim yearlyBonus As Decimal = 4000
Public Sub PrintSalary()
' print the salary to the Console
Console.Write(salary)
End Sub
Public Shared Sub Main()
Dim employee As Employee
employee = New Employee()
employee.PrintSalary()
End Sub
End Class
Now, you can use the Console
class in the PrintSalary
method without mentioning the namespace because the namespace is already imported. Namespaces also allow you to have classes with the same name in different namespaces. To refer to a class correctly, it is common practice to mention the namespace in front of the class name. For example, the Console
class in the System
namespace is referred to as System.Console
. Access Types
In many cases, when you write a class, you will provide that class to other people so they can use its functionality, i.e., they can call methods of that class or access its fields. One of the great benefits of OOP is that you can restrict access to a class member. This means, you have full control over what you want to expose. You can write methods that can be called by other programmers, or you can have methods that are not accessible by anyone other than from inside the class itself.VB.NET offers levels of accessibility, as follows:
- Public. Public class members don't have access restrictions. You use the keyword
Public
in front of the class member to make it available publicly. For example, thePrintSalary
method in theEmployee
class is a public method. It can be called from anywhere. - Private. Private class member can only be accessed from inside the class itself. Use the
Private
keyword to make a class member private. - Protected. A protected member is accessible to a derived class and from inside the class itself. Use the
Protected
keyword to make a member protected. - Friend. Members with the
friend
access restriction are accessible only within the program that contains the class declaration. Use the keywordFriend
to make a member have friend restriction. - Protected friend. This is the union of
protected
andfriend
.
Looking at the
Employee
class in Listings 4, 5 and 6 again, you may wonder why we can use the Write
method of the System.Console
class without first instantiating a System.Console
object. This is because in OOP languages there is a special type of member called a static member. The term shared is also used in VB.NET. Static means the member is available without having to instantiate an object. For example, the class called
SalaryLevel
provides static fields only in Listing 7. Listing 7: Static members in a class
Class SalaryLevel
Public Shared Level1 As Decimal = 35000
Public Shared Level2 As Decimal = 40000
Public Shared Level3 As Decimal = 45000
Public Shared Level4 As Decimal = 50000
Public Shared Level5 As Decimal = 55000
Public Shared Level6 As Decimal = 60000
Public Shared Level7 As Decimal = 65000
Public Shared Level8 As Decimal = 70000
Public Shared Level9 As Decimal = 75000
Public Shared Level10 As Decimal = 80000
End Class
You can then use the class in your program, as illustrated in Listing 8.Listing 8: Using a static member of a class
Imports System
Class SalaryLevel
Public Shared Level1 As Decimal = 35000
Public Shared Level2 As Decimal = 40000
Public Shared Level3 As Decimal = 45000
Public Shared Level4 As Decimal = 50000
Public Shared Level5 As Decimal = 55000
Public Shared Level6 As Decimal = 60000
Public Shared Level7 As Decimal = 65000
Public Shared Level8 As Decimal = 70000
Public Shared Level9 As Decimal = 75000
Public Shared Level10 As Decimal = 80000
End Class
Class Employee
Dim yearlyBonus As Decimal = 4000
Public Sub PrintSalary()
' print the salary to the Console, use the static field of SalaryLevel
Console.Write(SalaryLevel.Level4)
End Sub
Public Shared Sub Main()
Dim employee As Employee
employee = New Employee()
employee.PrintSalary()
End Sub
End Class
In the PrintSalary
method of the Employee
class, we can use the Level4
static field in the SalaryLevel
class without first creating an object of type SalaryLevel
. Members that are not static are called instance members.Constructors
A constructor is a special method that must be present in a class for the class to get instantiated. In VB.NET, this method is calledNew
. But, as you have seen, there is no New
method in the classes in the previous code. That's right. When there is no constructor present, VB.NET will create one for you. When you instantiate an object by using the New
keyword, the class's constructor is called. You can provide initialization code that is guaranteed to run when the object is instantiated. If you write a constructor explicitly in your class, VB.NET won't create it anymore. Inheritance
Inheritance is a feature that allows you to extend a class. If you need some functionality, you can create a brand new class. If part of the functionality you need has been provided in a class written by someone else, however, you can then write a new class that extends the original class. Your class is called the child class or derived class, and the original class is called the parent class or the base class. The process of extending a class is called extension. Sometimes, the term subclass or inherit is used to describe the act of extending a class. In VB.NET a class can only extend one parent class. Multiple class inheritance is not allowed in VB.NET.Syntactically, extending a class is done using a semicolon after the class name, followed by the word
Inherits
and the parent class name. For example, Listing 9 shows how we extend the class Employee
to create a new class called Manager
. Listing 9: Extending a class
Imports System
Class Employee
Dim salary As Decimal = 40000
Dim yearlyBonus As Decimal = 4000
Public Sub PrintSalary()
' print the salary to the Console
Console.Write(salary)
End Sub
End Class
Class Manager: Inherits Employee
End Class
If the word Inherits
appears on the next line, you don't need the semicolon.
Class Manager
Inherits Employee
End Class
Now, you can instantiate a Manager
object and use members from the Employee
class. The code is given in Listing 10. //////QUESTION: IMPORTS SYSTEM WAS STUCK IN THE ABOVE GRAF. IT PROBABLY BELONGS AS TEH FIRST LINE OF CODE. CHECK WITH AU.//////////Listing 10: Instantiating a Manager object
Imports System
Class Employee
Public salary As Decimal = 40000
Public yearlyBonus As Decimal = 4000
Public Sub PrintSalary()
' print the salary to the Console
Console.Write(salary)
End Sub
End Class
Class Manager: Inherits Employee
End Class
Module Module1
Public Sub Main()
Dim manager As Manager
manager = New Manager()
manager.PrintSalary()
End Sub
End Module
The example in Listing 11 shows how we can extend the Manager
class by writing a new method called PrintBonus
. Listing 11: Adding a method to the derived class
Class Manager: Inherits Employee
Public Sub PrintBonus()
Console.Write(yearlyBonus)
End Sub
End Class
Note that member accessibility restriction applies. For example, you can't make the yearlyBonus
field private, since this field is not accessible from the Manager
class. Therefore, trying to compile the code will result in an error. Inheritance is a common practice. In fact, the .NET Framework class library consist of hierarchies of classes that are derived from other classes. For example, the
Button
class in the Windows.Forms
namespace is a child class of ButtonBase
, which itself is a child of Control
. All classes will eventually have the System.Object
class as its root. System.Object
is called the root or the superclass in the .NET Framework class library. The power of inheritance can be demonstrated by the code in Listing 12.
Listing 12: Extending System.Windows.Forms.Form
Public Class MyForm : Inherits System.Windows.Forms.Form
End Class
This blank class declaration, when compiled and run, will display a Windows form. You can create a form without a single line of code. This is because MyForm
inherits System.WIndows.Forms.Form
. It inherits the functionality of the Form
class. NotInheritable Classes
You can prevent classes from being inherited by using theNotInheritable
keyword. For example, the code in Listing 13 is a class called Calculator
that cannot be inherited. Listing 13: A non-inheritable class
NotInheritable Class Calculator
End Class
Trying to extend this class will raise a compile error. Why would you want to make your class non- inheritable? In some cases, you may not want other people to be able to extend your class. Another reason is that an inheritable class produces faster code. You should use inheritable classes with caution, however, because noninheritance defeats the purpose of OOP. Only use it if you are 100% sure that you will not extend the class. This type of class is also called a final class in some other OOP languages. Method Overloading
A method is either a subroutine or a function. The difference, of course, is that a function in Visual Basic returns a value, while a subroutine does not. Both functions and subroutines can accept arguments.When choosing method names, you should, of course, use a name that reflects what the method does. But there are situations where you need methods that do similar things but accept different lists of arguments. For example, you may need a method that prints a double, as well as a method that prints a string. What do you do? You can write two methods and call them
PrintDouble
and PrintString
respectively. But you really want to call both methods Print
, because that is what they do. OOP languages, including VB.NET, allow multiple methods to have the same name, as long as those methods have different lists of arguments. This is called method overloading. Each of the methods with the same name is comfortably called an overload. In VB.NET, you add the keyword
Overloads
as the first part in the method signature. The use of the Overloads
keyword is optional, however; you can still have methods with the same name without using the keyword. For example, consider Listing 14, which shows the class Calculator
with two Add
methods. The first overload accepts two integers and the second overload accepts two doubles.
Imports System
Class Calculator
Overloads Public Function Add(a As Integer, b As Integer) As Integer
Add = a + b
End Function
Overloads Public Function Add(a As Double, b As Double) As Double
Add = a + b
End Function
End Class
Module Module1
Public Sub Main()
Dim counter As Calculator
counter = New Calculator()
' pass two integers
Console.WriteLine(counter.Add(1, 5))
' pass two doubles
Console.WriteLine(counter.Add(1.3, 5.9))
End Sub
End Module
In theMain
sub in theModule1
module, we instantiate aCalculator
object and call theAdd
method twice. On the first call to theAdd
method, we pass two integers, 1 and 5.
' pass two integers
Console.WriteLine(counter.Add(1, 5))
On the second call, we pass two doubles, 1.3 and 5.9. ' pass two doubles Console.WriteLine(counter.Add(1.3, 5.9))
Method overloading can also be found almost everywhere in the .NET Framework Class Library. Take the
Console
class in the System
namespace as an example. This class has a method named Write
that outputs the representation of a value to the console. The Write
method has 18 overloads. There is one overload that accepts a Boolean, one that accepts an integer, and so on. These overloads make sure that you can pass any type of data to the Write
method and the method will still work correctly. Beginners to OOP often make the mistake of thinking that methods can be overloads if the return values are of different types. This is not the case. In order to be an overload, the method must accept a unique set of arguments. Two methods with the same name that accept the same list of arguments will not compile, even though they return different return types.
For instance, the
Calculator
class in Listing 15 will not compile because the two Add
methods have the same set of arguments, even though the types of their return values are different. Listing 15: Incorrect method overloading
Imports System Class Calculator Overloads Public Function Add(a As Integer, b As Double) As Decimal Add = a + b End Function Overloads Public Function Add(a As Integer, b As Double) As Double Add = a + b End Function End Class
When you compile the class, it will report the following compile error: error BC30301: 'Public Overloads Function Add(a As Integer, b As Double) As Decimal' and 'Public Overloads Function Add(a As Integer, b As Double) As Double' differ only by return type. They cannot overload each other.
Why doesn't the compiler allow that? Because a function can be called without expecting a return value. For example, in the case of the erroneous
Calculator
class, if the compiler allowed that and the programmer called the Add
function by passing an integer and a double like this: Dim counter As Calculator counter = New Calculator() ' pass two integers counter.Add(1, 5.89)
it would not be clear which overload is being called. Method Overriding
Sometimes when you extend a base class, you may want to have a method that has the same name as the one in the base class but does something different. In VB.NET you can do this by using the keywordOverridable
in front of the declaration of the method in the base class. Then, in the derived class, you use the keyword Overrides
in front of the method with the same name. This technique is called method overriding. For example, Listing 16 shows a class called
Employee
with a method called Work
. The method is declared overridable, meaning that the method can be overridden in the inheriting classes. Listing 16: An overridable method
Imports System Class Employee Overridable Public Sub Work() Console.Write("I am an employee.") End Sub End Class
The code in Listing 17 is a class called Manager
that extends the class Employee
in Listing 16. In the Manager
class, we provide a different implementation for the method Work
. Listing 17: Method overriding
Class Manager: Inherits Employee Overrides Public Sub Work() Console.Write("I am a manager.") End Sub End Class
You can make a method not overridable by using the keyword NotOverridable
. For example, the Work
method in the Employee
class in Listing 18 cannot be overridden. Listing 18: Not overridable method
Imports System Class Employee NotOverridable Public Sub Work() Console.Write("I am an employee.") End Sub End Class
Abstract Classes
In some cases, you don't know how to write the implementation of a method in a class at the time of writing the class. Implementation can only be provided by the inheriting class. Or, you know that the method will be overridden in the child classes, so why bother providing an implementation at all? If this is the case, your class is incomplete; this is called an abstract class. The method that you don't provide implementation for is called an abstract method. An abstract method is denoted by theMustOverride
keyword. The class itself has the MustInherit
modifier because it cannot be instantiated using the New
keyword. For example, the class in Listing 19 is named
Shape
and it is abstract because one of the methods (Draw
) does not have implementation. Other than that, the class looks like a normal class. Listing 19: An abstract class
Imports System MustInherit Class Shape Public x As Integer = 9 Public y As Integer = 0 MustOverride Sub Draw() Public Function GetInfo() As String GetInfo = "An abstract class" End Function End Class
Note that the Draw
method does not have the End Sub
declaration. When you extend an abstract class, you must provide implementations for all methods that must be overridden. Otherwise, the inheriting class itself will be an abstract class and must be declared with the
MustInherit
keyword. The
Rectangle
and Line
classes in Listing 20 inherit Shape
. Listing 20: Inheriting from an abstract class
Class Rectangle: Inherits Shape Overrides Sub Draw() ' Draw a rectangle here End Sub End Class Class Line: Inherits Shape Overrides Sub Draw() ' Draw a line here End Sub End Class
Interfaces
For beginners, interfaces are probably not very clear. Why would you want to use an interface at all? An interface defines a contract that classes must adhere to.An interface is like an abstract class. An abstract class can have methods with or without implementations; however, an interface can only have methods that don't have implementation. In an OOP language that supports only single class inheritance like VB.NET, inheritance plays a very important role. Interfaces enable multiple inheritance in VB.NET because a VB.NET class can extend multiple interfaces. Extending an interface has a special term: implement. To implement an interface in VB.NET, you use the keyword
Implements
. As with extending an abstract class, you must provide implementations for all methods in the interface you implement. Otherwise, you must make your class abstract. An interface is declared using the keyword
Interface
. Like other types in VB.NET, there is a naming convention for interfaces. The recommendation is to use the class's naming convention and prefix the interface name with an I. For example, here are some good names for interfaces: IScalable
, ISerializable
, I3DShape
, IPolygonShape
, etc. For example, Listing 21 presents an interface called IShape.
Listing 21: An interface called IShape
Interface IShape End Interface
For a class to implement an interface, the same syntax as class extension is used. In the code in Listing 22, the class Line
implements the IShape
interface. Listing 22: Implementing an interface
Interface IShape End Interface Class Line: Implements IShape End Class
An alternative syntax would be: Interface IShape End Interface Class Line Implements IShape End Class
An interface in VB.NET can only have methods, properties and events. An interface cannot contain a field. All interface members are implicitly public and may not specify an access modifier. In the class that implements an interface, each method implementation must specify the interface method that it implements using the keyword Implements
, followed by the name of the interface and the method name. The interface name and the method name are separated using a period. For example, the code in Listing 23 shows an interface called IShape
with one method called Draw
. There is also a class named Line
that implements IShape
. Listing 23: Implementing an interface method
Imports System Interface IShape Sub Draw() End Interface Class Line Implements IShape Sub Draw() Implements IShape.Draw Console.Write("Draw a line") End Sub End Class
You can then instantiate a Line
object as you would a normal class. Like abstract classes, interfaces cannot be instantiated.Polymorphism
Polymorphism is probably the hardest concept to digest for those new to OOP. Indeed, polymorphism (literally means "many forms") is probably the most misunderstood term in OOP because the word has more than one meaning. For example, if you type in the word polymorphism as a search keyword in an Internet search engine, you will find out that this word is also used in biology.In modern software engineering discipline, polymorphism is classified into universal polymorphism and ad-hoc polymorphism. Universal polymorphism is considered purer than ad-hoc polymorphism and is also called "true polymorphism." Ad-hoc polymorphism is often described as "apparent polymorphism." Universal polymorphism is subdivided into parametric polymorphism and inclusion polymorphism; and ad-hoc polymorphism can be subdivided into overloading and coercion. These polysyllabic forms of polymorphism are explained below.
- Parametric polymorphism is the purest form of polymorphism*. The same object or function can be used uniformly as a parameter in different type contexts without changes. A function can be thought as parametric polymorphic if it allows the type of its parameters to be determined by an implicit or explicit type parameter, and then performs the same kind of work irrespective of the parameter type.
- Inclusion polymorphism is what we know as subtyping and inheritance. This type of polymorphism allows an object to belong to a number of classes, which are sometimes overlapping. In other words, a class can be included in another class to create an inheritance hierarchy.
- Overloading is what is known as method overloading in object-oriented programming languages. It allows multiple functions to have the same name, yet still perform different functions.
- Coercion allows a parameter to a function to be converted to the type expected by that function to avoid a type error.
In OOP, when we talk about polymorphism, it simply means "one interface, many implementations." To be more specific, the term is used to describe reference variables that may at run-time refer to objects of different classes. (Overloading is also a type of polymorphism; however, in OOP it is simply referred to as method overloading.) In other words, polymorphism (as far as OOP is concerned) simply means that you can assign to an object reference an object whose type is different from the object reference. In essence, if you have an object reference a whose type is A, it is legal to assign and object of type B, as in the following.
Dim a As A
a = New B()
However, B must be derived from A either directly or indirectly, or A must be an interface that is implemented by B or the class that B extends directly or indirectly. Consider the example in Listing 24.
Listing 24: An example of polymorphism
Class Employee
Public Overridable Sub Work
System.Console.WriteLine( "I am an employee." )
End Sub
End Class
Class Manager : Inherits Employee
Public Sub Manage
System.Console.WriteLine("Managing ...")
End Sub
Public Overrides Sub Work
System.Console.WriteLine( "I am a manager" )
End Sub
End Class
Module ModMain
Sub Main()
Dim employee As Employee
employee = New Manager
employee.Work
End Sub
End Module
The example has two classes: Employee
and Manager
. Employee
has a method called Sub
and Manager
extends the class Employee
and adds a new method called Manage
. The Main
sub in the module defines an object variable called employee of type Employee
.
Dim employee As Employee
However, employee
is assigned an object of type Manager
, as in
employee = New Manager
Then, when the Work
method is called, guess what is written on the console? I am a manager.
This means that it is the Work
method of Manager
class that gets called. Polymorphism in action! But why do we declare
employee
as Employee
in the first place? Why don't we declare employee
as Manager
? To ensure flexibility in cases where we don't know whether the object reference (employee
) will be assigned an object of type Manager
or something else. The next example will make it clearer why we use polymorphism. Say you have a Windows application and you have a method that changes the
BackColor
property of a control. You want to be able to pass a Button
, a Label
or any control that may be used in a form. For this purpose, you write the subroutine in Listing 25. Listing 25: The ChangeColor subroutine
Private Sub ChangeColor(_
ByVal control As System.Windows.Forms.Control, _
ByVal color As system.Drawing.Color)
control.BackColor = color
End Sub
You pass two arguments to the ChangeColor
sub: a System.Windows.Forms.Control
object and a System.Drawing.Color
object. You know that the Control
class is the parent class of all Windows controls. By declaring control
as Control
, polymorphism allows you to pass a Control
object or any object whose class is derived from the Control
class. This way, you only need one sub for all controls. Without polymorphism, you need a sub for each type of control. You would have ChangeButtonColor
, ChangeLabelColor
, etc The code in Listing 26 iterates all controls in a Windows form and passes each control to the
ChangeColor
sub. Running this code will give all controls in the current window a blue background color. Listing 26: Passing different controls to the ChangeColor subroutine
Dim control As System.Windows.Forms.Control
For Each control In Me.Controls
ChangeColor(control, Color.Blue)
Next
Summary
By now, you should have a much better understanding of all those cool words I presented at the beginning of the article. With this understanding, you can start to take advantage of VB.NET's complete support for object-orienting programming. Happy OOPing!http://ondotnet.com
Tidak ada komentar:
Posting Komentar