473,769 Members | 2,376 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Polymorphism and inheritance patterns in VB

The classing Visual Basic and VBA support for polymorphism, let's face it, is
a bit on the weak side, and built-in support for inheritance is non-existent.
This little essay is about some patterns I've ended up using successfully for
certain kinds of inheritance and polymorphism, and some that have not worked
out so well.

Let's start with obvious things that turn out not to work well:
1. Use interface classes and "Implements " for polymorphism:

At first glance, this seems like a fine choice. After all, in languages like
Java, interface implementation is used by most programmers at least as often
as inheritance, and is better than inheritance for many things. Also, using
interfaces allows for polymorphism without breaking type safety. Alas, in VB
things are not as good as they at first appear.

As it turns out, interfaces and Implements are useful sometimes in limited
circumstances, but the way they work in VB makes them often take extra effort
to maintain and makes them behave unpredictably in many circumstances.
First of all, rather than simply requiring that all the interface members be
implemented and making them visible through the interface like Java would do,
VB requries you to explicitly create an implementation of each method for each
interface using a qualified name. Each of these is then a separate method
that can its own different implementation (oh what a tangled web that could
be), and to make all cases act the same (like you want about 100% of the
time), you must explicitly call one central method from each of the interface
implementations fo the case.

Now, if that weren't bad enough, you'd best be careful never to mix early
binding and late binding code on the same classes in the wrong order because
if you set an Object variable equal to a variable of an interface type, the
object behaves as an instance of the interface it was in before you assigned
it. In other words, even though it is now housed in an Object variable, you
can't access any members or attributes of the object other than the ones
exposed through the last interface it used as before it went -in- to the
Object variable. What a mess.
2. Using composition and delegation to simulate inheritance:

Since you can't have one class implicitly inherit from and extend another, the
next thing that comes to mind is to create an "inheriting " class that exposes
the same methods as and contains an instance of the parent class, then
forwards calls to the contained "parent" from any method that is not supposed
to override the parent behavior.

In practice, this is a seious hassle. If you use interfaces, the compiler
will tell you when a change to the parent necessitates a change to the
"inheriting " class, but with all the overhead of interfaces discussed above.
If you use late binding and no interfaces, then you don't have the hassle, but
you also don't have the compiler forcing you to update the inheriting classes
when a parent changes, and it can be a lot of effort tracking them down. As a
final blow, you can't inherit and override anything private to the "parent"
class.
Next, for some things that often do work well.

1. Using late binding for polymorphism:

Rather than using interfaces, you can simply allow code to use instances of
certain classes polymorhically by storing everything in a simple Object
variable.

This technique does have some notable down-sides, but the up-sides can often
outweigh it. The biggest down-side is that the compiler can't make sure that
only classes that follow a particular interface can be passed to procedures
that expect to use that interface. If it breaks, it will break at run-time.
The big up-side is that it doesn't require much code overhead at all.

If there's a part of your code that's really begging for a large number of
classes to be used interchangeably by some procedures, this may be a good way
to go. To mitigate the down-sides, try to make sure code that's written this
way will pass instances of every class that might be passed, and call
everything that might be called one each one early in testing. That way, if
you do break something, you'll know about it before you deploy it. If
necessary, write some automated tests as insurance, and run them before each
deployment.
2. Use inverted containership (I believe my way of doing this is a version of
the "Decorator Pattern").

In this pattern, you implement something resembling inheritance by having one
class that always acts as the interface layer, and its run-time behavior is
determined by what kind of class instance it is encapsulating at run-time. In
other words, you might "decorate" a clsQuery class by supplying it with an
instance of clsInvoiceLineQ uerySpec. clsQuery provides the publicly
accessible interface, and clsInvoiceLineQ uerySpec has method signatures
clsQuery understands that provide the clsQuery instance with specific data
constants and procedures that enable it to operate in a specific context (e.g.
a SQL string).

Note that in this case, it can be somewhat practical to use an "Interface" for
the specific classes to define what they must make available to the general
interface class. The specific classes might never need to be accessed any
other way than through that interface, so there are no ambiguities or wrapped
calls to worry about.

3. Instances as "classes":

In many cases, it is sufficient to customize the behavior of an object through
initialization data alone. In this case, you can have a public function that
initializes an object with the correct data, and returns it. A form of
inheritance can be implemented in this scheme by supplying each class with a
Clone procedure, so you can clone one and extend or modify its behavior to
handle a more specific case.

For instance, let's say I have a class clsQuery that gets all its behavior
from the values of members called ParametersClaus e, SelectList, FromClause,
WhereClause, GroupByClause, and HavingClause. Now, let's say you provide a
public function called InvoiceLineQuer y that initializes a clsQuery instance
with SelectList = "tblInvoiceLine s.*" and FromClause = "tblInvoice s". Now,
you have an object that can query the entire tblInvoiceLines table.

Now, implement another function called InvoiceLinesFor Invoice that calls
InvoiceLineQuer y to get an instance, then sets ParametersClaus e =
"prmInvoice Id Long" and WhereClause =
"tblInvoiceLine s.InvoiceId=prm InvoiceId". This instance can be used to query
just the lines for a particular invoice.

As you can see, this can be a reasonably useful sort of real inheritance.
Note that .NET does similar things with the WindowsForms model. Each
WindowsForm object is constructed at run-time, but the code structures that do
the construction allow for a sort of inheritance by sequential addition of
items to the form's collections. I believe this is another sort of
implementation of the "Decorator Pattern".
Nov 13 '05
12 7056
Hi Jim,

....
http://www.exciton.cs.rice.edu/JavaR...egyPattern.htm

I really like this idea. Can you post code for a small example?
Thanks,
JAF
I finally got time to make up a little example for ya in addition to the one
RKC posted. This is not air code - it's tested and it works, though it is
obviously missing some error handling it would need for use in a production
app.

=== Module: basTestLogWrite r
Option Compare Database
Option Explicit

Public Sub TestTxtFileLogW riter()
Dim objWriterStrate gy As New clsLogWriterTxt FileStrategy

objWriterStrate gy.FilePath = CurrentProject. Path & "\" & _
"LogWriterTest. txt"

WriteLogData objWriterStrate gy

End Sub

Public Sub TestTableLogWri ter()
Dim objWriterStrate gy As New clsLogWriterTab leStategy

With objWriterStrate gy
.DbFilePath = CurrentProject. Path & "\" & _
"Log Writer Test Output.mdb"
.TableName = "tblLogEntr y"
.FieldName = "LogEntryTe xt"
End With

WriteLogData objWriterStrate gy

End Sub

Private Sub WriteLogData(Wr iterStrategy As ILogWriterStrat egy)
Dim objWriter As New clsLogWriter

objWriter.Setup WriterStrategy
objWriter.OpenL og

With objWriter
.WriteMessage "Test message 1"
.WriteMessage "Test message 2"
End With

objWriter.Close Log

End Sub

=== Module: clsLogWriter
Option Compare Database
Option Explicit

Private mobjStrategy As ILogWriterStrat egy

Public Sub Setup(Strategy As ILogWriterStrat egy)
Set mobjStrategy = Strategy
End Sub

Public Property Get Strategy() As ILogWriterStrat egy
Set Strategy = mobjStrategy
End Property

Public Sub OpenLog()
Strategy.OpenLo g
End Sub

Public Sub CloseLog()
Strategy.CloseL og
End Sub

Public Sub WriteMessage(Me ssage As String)
Dim strFormattedMsg As String

strFormattedMsg = FormatMessage(M essage)
Strategy.WriteF ormattedMsg strFormattedMsg

End Sub

Private Function FormatMessage(M essage As String) As String
Const cstrTimestampFo rmat = "yyyy-mmm-dd hh:nn a/p"
Dim strTimestamp As String

strTimestamp = Format(Now, cstrTimestampFo rmat)
FormatMessage = BulletChar & " " & _
strTimestamp & ": " & _
Message
End Function

Private Function BulletChar() As String
BulletChar = Chr$(149)
End Function

=== Module: ILogWriterStrat egy
Option Compare Database
Option Explicit

Public Sub OpenLog()
End Sub

Public Sub CloseLog()
End Sub

Public Sub WriteFormattedM sg(Message As String)
End Sub

=== Module: clsLogWriterTxt FileStrategy
Option Compare Database
Option Explicit

Implements ILogWriterStrat egy

Public FilePath As String

Private mintFileNum As Integer

Public Sub ILogWriterStrat egy_OpenLog()
mintFileNum = FreeFile
Open FilePath For Output As mintFileNum
End Sub

Public Sub ILogWriterStrat egy_CloseLog()
Close mintFileNum
End Sub

Public Sub ILogWriterStrat egy_WriteFormat tedMsg( _
Message As String _
)
Print #mintFileNum, Message
End Sub

=== Module: clsLogWriterTab leStategy
Option Compare Database
Option Explicit

Implements ILogWriterStrat egy

Public DbFilePath As String
Public TableName As String
Public FieldName As String

Private mdbsLogDb As DAO.Database
Private mrstLogTable As DAO.Recordset

Public Sub ILogWriterStrat egy_OpenLog()
Set mdbsLogDb = Workspaces(0).O penDatabase(DbF ilePath)
Set mrstLogTable = mdbsLogDb.OpenR ecordset(TableN ame, _
dbOpenDynaset, _
dbAppendOnly)
End Sub

Public Sub ILogWriterStrat egy_CloseLog()
mrstLogTable.Cl ose
mdbsLogDb.Close
End Sub

Public Sub ILogWriterStrat egy_WriteFormat tedMsg( _
Message As String _
)
mrstLogTable.Ad dNew
mrstLogTable(Fi eldName) = Message
mrstLogTable.Up date
End Sub
On 16 Dec 2004 10:32:46 -0800, ji********@comp umarc.com wrote:

Steve Jorgensen wrote:
On Thu, 16 Dec 2004 02:12:53 GMT, rkc

<rk*@rochester .yabba.dabba.do .rr.bomb>
wrote:

OK, I get it now. From what I can tell, the pattern I'm describing

most
closely resembles the "Strategy Pattern".

http://www.exciton.cs.rice.edu/JavaR...egyPattern.htm

I really like this idea. Can you post code for a small example?
Thanks,
JAF


Nov 13 '05 #11
rkc
Steve Jorgensen wrote:
Hi Jim,

...
http://www.exciton.cs.rice.edu/JavaR...egyPattern.htm

I really like this idea. Can you post code for a small example?
Thanks,
JAF

I finally got time to make up a little example for ya in addition to the one
RKC posted. This is not air code - it's tested and it works, though it is
obviously missing some error handling it would need for use in a production
app.


Usefull example. It's pretty clear how it could be easily extended to
write to an XML file, another database or even an spreadsheet.
You also got the handling of the data in the context class
(clsLogWriter)w here it belongs. I got that wrong. Not sure why you
expose Private mobjStrategy with a property get though.

The file setup code in the test module is ugly, but then I realized
in real life you would probably handle that in the strategy classes
via config data stored outside the application code.


Nov 13 '05 #12
On Mon, 20 Dec 2004 01:06:06 GMT, rkc <rk*@rochester. yabba.dabba.do. rr.bomb>
wrote:
Steve Jorgensen wrote:
Hi Jim,

...
http://www.exciton.cs.rice.edu/JavaR...egyPattern.htm

I really like this idea. Can you post code for a small example?
Thanks,
JAF

I finally got time to make up a little example for ya in addition to the one
RKC posted. This is not air code - it's tested and it works, though it is
obviously missing some error handling it would need for use in a production
app.


Usefull example. It's pretty clear how it could be easily extended to
write to an XML file, another database or even an spreadsheet.
You also got the handling of the data in the context class
(clsLogWriter) where it belongs. I got that wrong. Not sure why you
expose Private mobjStrategy with a property get though.


That was a case of "I needed it last time, so..." Frankly, I don't remember
why I need a public Strategy member, so I probably should have left it out
until the need arises again.
The file setup code in the test module is ugly, but then I realized
in real life you would probably handle that in the strategy classes
via config data stored outside the application code.


Pretty much, yeah. This was the minumum code I thought I could write that
would fully demonstrate the template pattern, and why it would be useful.

Nov 13 '05 #13

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

37
2848
by: Mike Meng | last post by:
hi all, I'm a newbie Python programmer with a C++ brain inside. I have a lightweight framework in which I design a base class and expect user to extend. In other part of the framework, I heavily use the instance of this base class (or its children class). How can I ensure the instance IS-A base class instance, since Python is a fully dynamic typing language? I searched and found several different ways to do this:
0
1282
by: Faraz | last post by:
Is it possible to create a inheritance heirarchy for the web service proxy class that inherits the SoapHttpClientProtocol?? I am trying to create a superclass that inherits from SoapHttpClientProtocol called Project, and create several subclasses of it. Then I try to use factory patterns and polymorphism to send the Request and Response messages - ( I have a heirarchy for them too).. Somehow it does not work. It keeps blowing up on my...
10
3034
by: Lino Barreca | last post by:
Take a look at this code: Class clsAnagrafica Public Overridable ReadOnly Property Codice() As Integer Get Return 1 End Get End Property End Class
13
3260
by: Fao | last post by:
Hello, I am having some problems with inheritance. The compiler does not not return any error messages, but when I execute the program, it only allows me to enter the number, but nothing else happend. I think the problem may be in my input function or in the main function. If anyone out there can help me it woul be greatly appreciated. Here is the code: #include <iostream>
60
4938
by: Shawnk | last post by:
Some Sr. colleges and I have had an on going discussion relative to when and if C# will ever support 'true' multiple inheritance. Relevant to this, I wanted to query the C# community (the 'target' programming community herein) to get some community input and verify (or not) the following two statements. Few programmers (3 to7%) UNDERSTAND 'Strategic Functional Migration
18
3864
by: Seigfried | last post by:
I have to write a paper about object oriented programming and I'm doing some reading to make sure I understand it. In a book I'm reading, however, polymorphism is defined as: "the ability of two different objects to respond to the same request message in their own unique way" I thought that it was: "the ability of same object to respond to different messages in
11
2977
by: chsalvia | last post by:
I've been programming in C++ for a little over 2 years, and I still find myself wondering when I should use polymorphism. Some people claim that polymorphism is such an integral part of C++, that anybody who doesn't use it might as well just program in plain C. I totally disagree with this, because I think C++ has a lot of great features apart from polymorphism, such as the ability to organize code into classes, code reuse through...
8
20612
by: weird0 | last post by:
Can anyone explain briefly what is the difference between inheritance and polymorphism? i read and seem to forget it again and again... Can anyone along with good examples of c# explain the fundanmental concept so i can remember it forever as it is a common interview question.... Thanks in advance
1
10102
weaknessforcats
by: weaknessforcats | last post by:
Introduction Polymorphism is the official term for Object-Oriented Programming (OOP). Polymorphism is implemented in C++ by virtual functions. This article uses a simple example hierarchy which you may have seen many times in one form or another. An analysis of this example produces several problems that are not obvious but which will seriously limit your ability to use hierarchies like the example in a real program. Then, the article...
0
9423
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10043
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
9990
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
8869
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
7406
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
5298
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
1
3956
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
3561
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2814
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.