any people ask about how the Implements statement is used in Visual Basic. It is actually quite useful and allows you to build more flexible applications. Here’s what it is all about:
The Implements statement is used as part of a technique that separates the interface of an object from its implementation, so that multiple implementations of the interface can be developed. The interface is defined as an abstract interface, and concrete classes inherit the interface using the Implements statement. Clients can then bind to the interface and dynamically switch these concrete classes used to fulfill the role of the interface. To explain this, let’s explore the following scenario:
Suppose we are creating an object for a company-wide application that we’ll call AccountTransfer. This component must have the ability to log all actions that it performs and the logging method will vary from client to client. We want to develop, compile, and distribute AccountTransfer without having to modify it for each client. To solve this problem we decide to encapsulate the logging functionality in a separate object. The logging object, called Log, has one method, called Execute, that takes a parameter, called Info. Clients will be responsible for creating this logging object. They will supply it to AccountTransfer by setting a property of AccountTransfer, called LogObject. Every time AccountTransfer performs a transaction it calls the Execute method of the Log object that was set by the client through the LogObject property.
The challenge is how to ensure that the client that creates the Log object gives it the correct method and parameter so that our component doesn’t crash. In other words, how do we do early binding to an object that hasn’t been created yet, and will vary from client to client? Using Implements we can define a standard description of the LogObject called an abstract interface. An interface is made up of the public properties and methods of an object. An abstract interface is simply the property and method declarations without any implementation code. We’ll call the abstract interface ILog (the “I” prefix is a naming standard for abstract interfaces). Once we’ve defined an abstract interface we can type the LogObject property as ILog. In order for clients to set the LogObject property, they will have to create a class that implements the LogObject’s abstract interface so that it can pass as the ILog data type.
The first step is to define the abstract interface for the Log object. To create an abstract interface in Visual Basic, add a class module to the project, name it, and insert the procedure declarations that define the interface. Do not put any code in the declaration stubs.
So for our sample component, we’ll add a class module to the project and name it ILog. Next we’ll add the following procedure stub to the class:
'***************** ILog ****************************Public Function Execute (Info as String) As BooleanEnd Function
Now we’ll add the LogObject property to the AccountTransfer object and type it as ILog:
'************* AccountTransfer ************************'*************Declarations SectionDim objLog as ILog'**************Public Property Set LogObject (Obj As ILog) Set objLog = ObjEnd Property
The procedure of AccountTransfer that has to perform the logging can now be sure that the Log object supplied by the client has the interface it expects. The procedure would call the Log object with the following code:
'***********Procedure of AccountTransfer Object************Public Sub ExecuteTransaction()Dim bSuccess as BooleanDim sLogInfo as String 'variable that stores the information
that has to be logged'code that executes the transaction goes here'now the transaction is loggedb = objLog.Execute (Info:=sLogInfo)End Sub
Now lets take a look at what a client has to do in order to supply a Log object to AccountTransfer’s LogObject property:
1. Set a reference in the client app to AccountTransfer, using the References dialog available from the Project/References menu. (This step is only necessary if AccountObject is in a separate project. If you are putting AccountTransfer and concrete class in one project, proceed to the next step.)
2. Add a class module to the client app, name it ConcreteLog.
3. Add the Implements statement followed by ILog to the Declarations section:
'*********ConcreteLog (client's concrete class that implements ILog)*********'Declarations SectionImplements ILog
Once the Implements statement is added to the ConcreteLog class module, it becomes a concrete class of ILog and therefore can be passed off as the ILog data type. In order for this type coercion to be valid, Visual Basic automatically adds the procedure declarations of the implemented abstract interface to the concrete class, which in our case is ILog’s Execute method. Visual Basic also ensures that the client has some code in all the inserted procedure stubs. It does this by raising a compiler error if any of them are empty. For our sample concrete class the following procedure declaration is added:
'*************ILog's Interface that is added to ConcreteLog**********Private Function ILog_Execute (Info As String) As Boolean'code for implementing the logging functionality for this particular
concrete class goes hereEnd Function
Once the concrete class is created, the client can instantiate an instance of it and set the AccountTransfer’s ObjectLog property to point to the instance with the following code:
'************Client Form that sets Accounttransfer.Objectlog to ConcreteLogDim objAcct As New AccountTransferDim objLog as new ConcreteLogSet objAcct.LogObject = objLog
Note how the client instantiates an instance of ConcreteLog and passes it as a parameter of the ILog type. Using this technique, each one of the clients of AccountTransfer can implement their own version of logging without having to modify AccountTransfer.
In summary, Implement allows you to create concrete classes that inherit a predefined abstract interface. Once the concrete class inherits the interface, it can assume the abstract interface’s data type. It can then be passed as a parameter, or set to a variable that is declared as the interface type. This enables you to write code that depends on a defined interface, but not on its implementation. The implementation can be added and changed without affecting your code. This technique can help you create easy-to-maintain, flexible solutions.
Here are a couple of things to note about Implements:
- The abstract interface’s procedure declarations are added to the concrete class as private. In order for a client to access those procedures as implemented in the concrete class, they have to first declare a variable of the interface’s type, and then set the variable to point to an instance of the concrete class as follows:
Dim objConcreteClass as Iinterface Set objConcreteClass = New ConcreteClass
This is essentially what we did in our sample: the client set the LogObject property that is of the ILog type to an instance ConcreteLog.
- A dynamic link is not maintained between an abstract interface and a concrete class. So, changes made to the abstract interface after the Implements statement was added to a concrete class will not be automatically propagated to the concrete class. This holds true even if the abstract interface and concrete class are in the same project.
- Event declarations of the abstract interface are not included in the interface that is inherited by concrete classes. I haven’t found anywhere that this has been acknowledged as a bug; however, it does seem to be one.
- The Visual Basic compiler forces you to put some code in each one of an implemented interface’s procedures. If you don’t need to implement a certain procedure, then you place a comment in the procedure and the compiler will be satisfied.