Implementing an interface


Let’s begin the process with a simple implementation of the filter class in Bug Wizard, CBug­Filter. The key statement in an interface implementation is the Implements statement. At first glance, there’s not much to it:

‘ CBugFilter implements IFilter
Implements IFilter

The interesting thing about this statement is not what it looks like, but what it does to the code window containing it. The object dropdown gets a new entry for IFilter. If you select IFilter, the procedure dropdown shows the event procedures that you must implement. When you select the Source property get procedure, the IDE automatically puts the cursor on the property method, if one exists, or creates a Source property get procedure if one doesn’t exist. The IDE creates the following procedure and puts the cursor on the blank line in the middle, ready for you to type in the implementation code:

Private Property Get IFilter_Source() As String

End Property

Interface procedures look like event procedures because, like event procedures, you can’t change their names. But unlike event procedures, you can’t ignore them. You must implement each and every member defined by the interface. By using the Implements keyword, you are signing a contract. You agree to implement all members exactly as they are defined in the interface. Try violating the contract. Change IFilter_Target to IFilter_Targot, or change the return type of IFilter_Translate to Integer. When you try to compile, Visual Basic will inform you in no uncertain terms that you are a cad and a deceiver and that you must fulfill your obligations if you wish to continue.


Here’s the interface part of the implementation I gave my CBugFilter class:

‘ Implementation of IFilter interface
Private sSource As String, sTarget As String

Private Property Get IFilter_Source() As String
IFilter_Source = sSource
End Property
Private Property Let IFilter_Source(sSourceA As String)
sSource = sSourceA
End Property

Private Property Get IFilter_Target() As String
IFilter_Target = sTarget
End Property
Private Property Let IFilter_Target(sTargetA As String)
sTarget = sTargetA
End Property

Private Function IFilter_Translate(sLine As String, _
ByVal iLine As Long) As EChunkAction
IFilter_Translate = ecaTranslate ‘ Always translate with this filter

Select Case eftFilterType
Case eftDisableBug
CommentOut sLine, sBug
Case eftEnableBug
CommentIn sLine, sBug
Case eftDisableProfile
CommentOut sLine, sProfile
Case eftEnableProfile
CommentIn sLine, sProfile
Case eftExpandAsserts
ExpandAsserts sLine, iLine
Case eftTrimAsserts
TrimAsserts sLine
End Select
End Function

Source and Target are unvalidated properties that you would normally implement with a Public member rather than with separate property procedures. The Implements statement won’t let you take that shortcut. If you look back at the IFilter class, you’ll notice that it also doesn’t take the Public member shortcut, although it could. You might want to experiment with Public members in interface classes, but don’t be surprised if Visual Basic makes choices about parameter names and ByVal attributes that you wouldn’t make yourself. By defining the Property Get and Let procedures yourself, you get better control over the code that will be used in the implemented class.


There’s no room for creativity in how you declare interface members in the implementing class. The creativity comes in the implementation of members such as the Translate function. Notice how the sLine parameter is passed by reference so that the modified version will be returned to the caller, but iLine is passed by value so that the caller’s copy can’t be changed.


As for what Translate actually does, it calls other procedures that do the actual work. If you reread the description of the Bug Wizard program, you can probably guess most of what these procedures are actually doing. The decision of which procedure to use is based on another property that is part of CBugFilter but not part of IFilter:

Property Get FilterType() As EFilterType
FilterType = eftFilterType
End Property

Property Let FilterType(eftFilterTypeA As EFilterType)
If eftFilterTypeA >= eftMinFilter And _
eftFilterTypeA <= eftMaxFilter Then
eftFilterType = eftFilterTypeA
Else
eftFilterType = eftMaxFilter
End If
End Property

This property uses an EFilterType Enum and an eftFilterType member variable (not shown). Next we’ll see how a client can use both the IFilter properties and the CBugFilter properties.