Abstract and Implementation Classes - MS Access

In this section, you look at an example of creating classes by using abstract and implementation classes. The example illustrates how to build classes that assist with data import and export. Although it costs some time to correctly construct class libraries, the benefit is that once you have them built and tested, you will get a lot of use out of them. The advantage of using abstract classes is that they create a definition that you need to follow when constructing additional classes, which helps you to ensure that you add all the required features when creating new classes.

Abstract Classes

An abstract class is a template for building other classes. It contains placeholders for your subs, functions, and properties. The functions, subs, and properties do not contain any code, because once they have been defined in the abstract class and you create a real (or concrete) class that implements the abstract class, you are forced to allow for a stub function, sub, or property to match each item in the abstract class. The derived classes then provide the code to implement the place holders defined in the abstract class. When using abstract classes you will also be using the Implements keyword to build classes that implement the abstract classes.

Abstract classes and code

Although an abstract class acts to provide a template for other classes to add implementation code, it is possible to place common code inside the abstract class; to make use of this shared code you need to create an instance of the abstract class inside an implementation class. In general, the term abstract class means that you do not create instances of the class, but in VBA, because an abstract class is not a special class in terms of how it is defined, you can create an instance of an abstract class.

An abstract class file is created in exactly the same way as any other class file. The samples database contains a class called clsExportImport, which will act as an abstract class, as demonstrated in the following (only part of the class in this and other examples will be shown):

Notice that the class does not have any member variables; it only has place holders for the properties and functions/subs. For the sake of convenience, the sample defines an enumerated type which is placed inside the abstract class. This will be used in the derived classes that you will be building.

Implementation Classes

The next step is to build specific implementation classes that follow the abstract class template. You do this by using the Implements keyword. There are two implementation classes: one called clsImportExportText for handling text files, and the other called clsImportExport- Excel for handling spread sheets. At the top of the file, define the member variables, as shown in the following:

If you select the class object as shown in Figure, you can view or create the two events associated with the class.

Adding an initialization for each class.

Adding an initialization for each class

Because you have entered the Implements keyword, you can now select the abstract class name from the drop-down menu. Items for which you already have a stub function are displayed in bold; those for which you need to add a stub function will not be bold.

Entries must be selected for every Let/Get property and every function/subroutine defined in the abstract class.

Entries must be selected for every Let/Get property and every function/subroutine defined in the abstract class.

One particular function in the abstract class—a stub function to Get the Filename—is defined as follows:

The line of code has been typed in and was not provided when the stub function was generated. The Get property of the class defined previously is not going to be visible as a property in the derived class. This is because it is marked as private. Also, look at the name clsImport Export_FileName; if you made it public, it would not look like a desirable name for a property.

This is quite subtle, and it is not until you actually implement the abstract class and trace the code execution path that it becomes clear what is happening. You will also notice in the code where Access has generated stub functions for Let statements that the parameter is named RHS; this means right-hand-side, which indicates that the Let statement will make an assignment using this variable on the right of an expression.

Implementing an Abstract Class

What lies at the heart of implementing an abstract class is the ability to work with an object variable that references the abstract class but that can point to any of the derived classes, but have the code executed in the derived class. So you can perform the following trick (look very carefully at the first two lines of code where the variable is of type clsImportExport, but you create an object with this variable of

Figure presents the result of tracing through the code execution into the derived classes code and also illustrates the parameter naming RHS, for right-hand-side generated by Access.

When a variable of the abstract class type is set to a derived class object, it executes the code in the derived class.

When a variable of the abstract class type is set to a derived class object, it executes the code in the derived class.

If you trace the execution in Debug mode, you find that the procedure and methods that are called are in the object type clsImportExportExcel; for example, this occurs when assigning the property ExportProcess.FileName. When you call a property with the name FileName (which is only defined in the abstract class), it actually executes the code in the derived class called clsImportExport_FileName. The abstract class exposes the property name but then hooks up the code to execute in the class that implements the abstract interface.

If you want to add a new property to your classes, you have two options. You can add a Let and Get (or for read-only, just a Get) to the clsImportExport, but if you do that, it means adding a stub procedure to all the derived classes. The second option is you can just add the new property to the derived class to which it applies. The question becomes, what happens if you just add something in the derived class? To demonstrate, in your clsImportExportText class, add the following Let and Get:

Now, in Debug mode, if you look at the ExportProcess properties, you will not see this new property. This is because it is not defined in the abstract class, so you need to create a new object variable of type clsImportExportText and make it point at the object. You can see an example of this in modImportExport_Testing, as shown in Figure.

This breakpoint in the Immediate window shows how you can use the extended property SpecificationName in the derived class.

This breakpoint in the Immediate window shows how you can use the extended property SpecificationName in the derived class.

So, you define a variable called EPText, which is of type clsImportExporText, and make it point to the object by using the following:

SET EPText = ExportProcess

You can now use the EPText object variable to access the extended properties defined in the derived class.

Establishing an object type with TypeOf You refer to an object by using an object variable that is defined as a type matching the abstract class.

The TypeOf statement allows you to establish the type of object being referenced through a variable defined as being of a type corresponding to the abstract class:

If you then want to use features specific to that class, you need to use the variable type matching that of the implementing class. What you have achieved in the sample code thus far is referred to in many programming languages as type casting of pointers; here you have done this through the features of VBA abstract classes.

You now have a property in the implementing class called clsImportExport_ImportData(), which is not exposed, and in the abstract class is called ImportData(). At first glance, this appears to be a problem, but it is not, because when you call the method with a pointer to an abstract class type (having created an implementing class for this object), it executes the code in the implementing class. This is a clever feature of abstract classes. If you need to explicitly expose the properties and methods in the abstract class when working with a variable referencing the implementing class, you can use the following technique to define a Public Function in the implementing class:

Using the previously described approach, you can hold and execute common code from within an abstract class; this extends the idea of an abstract class acting as a placeholder, to contain executable code. We wish to be clear about one point: a variable defined of type matching the abstract class type needs to be used when manipulating the properties defined in the abstract class, but a variable matching the type of the implementing class needs to be used when referring to features defined in the implementing class, but not in the abstract class.

Hybrid Abstract and Non-Abstract Classes

Purists will state outright that VBA fails to meet the accepted definitions of polymorphism and inheritance expected of object-oriented languages, and even though that is true, VBA does have some very clever features, such as using WithEvents, that go beyond the basic object-oriented definitions.

Although defining member variables and writing code in the abstract class is permitted, it does not appear to be a useful idea, because you cannot use these variables, or any code written in the abstract class (because an abstract class is a template). But you can add to a derived class a reference to an instance of the abstract class by using a form of wrapper around the abstract class. This might be a poor man’s version of inheritance, but it does lead to some interesting possibilities.

It is possible to mix and match features from abstract and non-abstract classes when implementing an interface. To show how this works, we have created a new base class called clsImportExport2. In this class, we have added a member variable p_FileName and changed the Let/Get to use this private member variable. This is now a hybrid class in that it is part concrete and part abstract:

In the new derived class called clsImportExportText2, you need to create an instance of the abstract class (you are both wrapping the class and implementing the class at the same time), as follows:

Because you are implementing this abstract class, you still need the appropriate entries for the FileName Let/Get, but you now call the code in the base/abstract class from the derived class:

When you develop a class, you invest a lot of time and effort constructing the class. And as you have seen, everything except the very essential elements that you need are private to a class. But if you devise a very useful private internal function in a class and then decide another class that wraps around this class needs to dig into its structure and use the internal function, then there is a method for doing this, and it involves the use of the Friend keyword.

Inside the class cls Import Export Text, there is an internal function called ExtractFileName, which extracts the file name from p_FileName (which includes the path and file name). If you create a new class called clsDemo Friend that wants to use this function, but you don’t want to simply expose this as a property of the class, then you define the function by using the Friend keyword. The following code iilustrates a modified definition of the function in the class clsImportExportText:

In the new class clsDemoFriend, you can work with ExtractFileName, which is the internal part of clsImportExportText. To do this, you need to create an instance of the object that contains the Friend function in the class, as follows:

This new class is then able to make a reference to the ExtractFileName() function, which is contained in clsImportExportText. The only reason that you are creating an instance of clsImportExportText is so that you can make use of the Friend function in that class. This is demonstrated in the procedure modFriend_Test.

All rights reserved © 2020 Wisdom IT Services India Pvt. Ltd DMCA.com Protection Status

MS Access Topics