Alternative to class interface

tiredofit

Well-known Member
Joined
Apr 11, 2013
Messages
1,832
Office Version
  1. 365
  2. 2019
Platform
  1. Windows
This video demonstrates how to use a class interface:

Code:
https://www.youtube.com/watch?v=3bO50gHRndA

and this is the code:

Code:
Option Explicit

' The Interface Class - this is implemented by clsInterestA, clsInterestB and clsInterestC

Sub Calculate(ByVal amount As Double)
End Sub

Sub PrintResult()
End Sub


' Class clsInterestA

Implements iInterest

Private m_Amount As Double

' Calculate the interest
Sub iInterest_Calculate(ByVal amount As Double)
    m_Amount = amount * 1.1
End Sub

' Print the result to the Immediate Window
Sub iInterest_PrintResult()
    Debug.Print TypeName(Me) & ": " & m_Amount
End Sub


' Class clsInterestB

Implements iInterest

Private m_Amount As Double

' Calculate the interest
Sub iInterest_Calculate(ByVal amount As Double)
    m_Amount = amount * 1.5
End Sub

' Print the result to the Immediate Window
Sub iInterest_PrintResult()
    Debug.Print TypeName(Me) & ": " & m_Amount
End Sub


' Class clsInterstC

Implements iInterest

Private m_Amount As Double

' Calculate the interest
Sub iInterest_Calculate(ByVal amount As Double)
    m_Amount = amount + 1000
End Sub

' Print the result to the Immediate Window
Sub iInterest_PrintResult()
    Debug.Print TypeName(Me) & ": " & m_Amount
End Sub

]/code]

This is in a standard module:

[code]

Option Explicit

Sub Main()

    ' Get the range of data
    Dim rg As Range
    Set rg = shData.Range("A1").CurrentRegion
 
    ' Declare the interface variable - this can reference any class
    ' that implements iInterest.
    Dim oInterest As iInterest
 
    ' data variables
    Dim amount As Double, interestType As String
 
    ' Read through the data
    Dim i As Long, result As Double
    For i = 2 To rg.Rows.Count
 
        ' read the current row to variables
        amount = rg.Cells(i, 1).Value
        interestType = rg.Cells(i, 2).Value

        ' Get the interest object
        Set oInterest = ClassFactory(interestType)
     
        ' Calculate the interest
        oInterest.Calculate amount
     
        ' some code
     
        ' Print the interest to the Immediate Window
        oInterest.PrintResult
       
    Next i

End Sub

Function ClassFactory(ByVal interestType As String) As iInterest

    Dim oInterest As iInterest
         
    If interestType = "A" Then
        Set oInterest = New clsInterestA
    ElseIf interestType = "B" Then
        Set oInterest = New clsInterestB
    ElseIf interestType = "C" Then
        Set oInterest = New clsInterestC
    Else
        MsgBox "Invalid type " & interestType
    End If
 
    Set ClassFactory = oInterest

End Function

Instead of using interfaces, why not just have a single class that takes a single parameter, either A, B or C.

Then within that class, write some If statements.

So for example:

Code:
' Single class

Option Explicit

    Private pInterestType As String
 
Private m_Amount As Double

Public Property Get InterestType() As String

    InterestType = pInterestType
 
End Property

Public Property Let InterestType(ByVal I As String)

    pInterestType = I
 
End Property


' Calculate the interest
Sub Calculate(ByVal amount As Double)
 
    Select Case InterestType
 
        Case "A"
     
            m_Amount = amount * 1.1
         
        Case "B"
     
            m_Amount = amount * 1.5
         
        Case "C"
 
            m_Amount = amount + 1000
         
    End Select
  
End Sub

' Print the result to the Immediate Window
Sub PrintResult()
    Debug.Print TypeName(Me) & ": " & m_Amount
End Sub

This is the standard module:

Code:
Option Explicit

Sub Main()

    ' Get the range of data
    Dim rg As Range
    Set rg = shData.Range("A1").CurrentRegion
 
    Dim oInterest As Class1
 
    ' data variables
    Dim amount As Double, InterestType As String
 
    ' Read through the data
    Dim I As Long, result As Double
    For I = 2 To rg.Rows.Count
 
        ' read the current row to variables
        amount = rg.Cells(I, 1).Value
        InterestType = rg.Cells(I, 2).Value

        Set oInterest = New Class1
     
        oInterest.InterestType = InterestType
     
        ' Calculate the interest
        oInterest.Calculate amount
     
        ' some code
     
        ' Print the interest to the Immediate Window
        oInterest.PrintResult
       
    Next I

End Sub

My alternative idea produces the same results, so what advantages would using interfaces bring or is it all about polymorphism?

Thanks
 

Excel Facts

How to change case of text in Excel?
Use =UPPER() for upper case, =LOWER() for lower case, and =PROPER() for proper case. PROPER won't capitalize second c in Mccartney
Your option is not easily scalable and if you have multiple methods/properties, you have to implement that choice logic in every single one. You also lose the ability to have classes that share some common parts but implement other specific functionalities.
 
Upvote 0
Solution
Your option is not easily scalable and if you have multiple methods/properties, you have to implement that choice logic in every single one. You also lose the ability to have classes that share some common parts but implement other specific functionalities.
Thanks.

As an extension to the original code, ie the one that DOES use interfaces, if I have a situation where a Sub is identical in all three classes, for example if I have this in clsInterestA:

Code:
Public Sub iInterest_Message()
    
    MsgBox "hi"
    
End Sub

obviously I would have to add this to the interface:

Code:
Public Sub Message()
    
End Sub

but for the two remaining classes, is it good (I've tested it and it works) to write:

Code:
Public Sub iInterest_Message()
    
    Dim a As clsInterestA
    Set a = New clsInterestA
    
    Call a.iInterest_Message
    
    Set a = Nothing
    
End Sub

or should I merely copy this:

Code:
Public Sub iInterest_Message()
    
    MsgBox "hi"
    
End Sub

into classes B and C?
 
Upvote 0
The latter. Encapsulation is kind of the point and you would also be generating a dependency for no real benefit.
 
Upvote 0
The latter. Encapsulation is kind of the point and you would also be generating a dependency for no real benefit.
Thanks.

I couldn't decide because using the former does adhere to the rule of "reusing code" , which (as far as I'm aware), is one of the principles behind using classes.
 
Upvote 0
The primary purpose is encapsulation though. It would be an odd situation for that to be the best option.
 
Upvote 0

Forum statistics

Threads
1,214,646
Messages
6,120,715
Members
448,985
Latest member
chocbudda

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top