Home > Back-end >  VBA Class Inheritance
VBA Class Inheritance

Time:02-21

I am working on a script to help me create geometry in 3D software based on user input and I wanted to approach the problem with classes. I have 3 levels of structures, points, curves and surfaces so I want to create a class for each, where the next level structure inherits the lower one. So for example class cPoint have 4 properties: x,y,z,id. Further, the class cCurve has only 2 properties: id and points, and the same for surfaces. Now my question is: I implemented class cPoint as follows:

Private x_ As Double
Private y_ As Double
Private z_ As Double
Private id_ As Long

Public Property Let X(ByVal value As Double)
    x_ = value
End Property
Public Property Let Y(ByVal value As Double)
    y_ = value
End Property
Public Property Let Z(ByVal value As Double)
    z_ = value
End Property
Public Property Let ID(ByVal value As Long)
    id_ = value
End Property
Public Property Get X() As Double
    X = x_
End Property
Public Property Get Y() As Double
    Y = y_
End Property
Public Property Get Z() As Double
    Z = z_
End Property
Public Property Get ID() As Long
    ID = id_
End Property

and everything is fine here. And here I have class cCurve implemented:

Implements cPoint

Private id_ As Long
Private point_ As Collection

Public Property Let ID(ByVal value As Long)
    id_ = value
End Property
Public Property Set point(ByVal value As Collection)
    Set point_ = value
End Property
Public Property Get ID() As Long
    ID = id_
End Property
Public Property Get point() As Collection
    Set point = point_
End Property

But here, when I try to run the code I get prompted with the following error: Object module needs to implement 'X' for interface 'cPoint' I think I know what it means, but I have no clue how to implement it. Is my approach even correct? I'd highly appreciate any guidance in this manner.

CodePudding user response:

VBA does not support inheritance. The only way to mimic inheritance is to implement your Point class and at the same time have a private instance of the Point class in your curve class. This is what your "Point" class would look like (I used "GeometryPoint" as the name of the class because Excel already has a "Point" class created):

Option Explicit

Private Type TState
    ID  As Long
    X   As Double
    Y   As Double
    Z   As Double
End Type

Private This As TState

Public Property Let ID(ByVal Value As Long)
    This.ID = Value
End Property
Public Property Get ID() As Long
    ID = This.ID
End Property

Public Property Let X(ByVal Value As Double)
    This.X = Value
End Property
Public Property Get X() As Double
    X = This.X
End Property

Public Property Let Y(ByVal Value As Double)
    This.Y = Value
End Property
Public Property Get Y() As Double
    Y = This.Y
End Property

Public Property Let Z(ByVal Value As Double)
    This.Z = Value
End Property
Public Property Get Z() As Double
    Z = This.Z
End Property

And this is what your "Curve" class would look like:

Option Explicit
Implements GeometryPoint

Private Type TState
    Base        As GeometryPoint
    ID          As Long
    Points      As Collection
    X           As Double
    Y           As Double
    Z           As Double
End Type

Private This As TState

Public Property Let GeometryPoint_ID(ByVal Value As Long)
    This.Base.ID = Value
End Property
Public Property Get GeometryPoint_ID() As Long
    GeometryPoint_ID = This.Base.ID
End Property

Public Property Let GeometryPoint_X(ByVal Value As Double)
    This.Base.X = Value
End Property
Public Property Get GeometryPoint_X() As Double
    GeometryPoint_X = This.Base.X
End Property

Public Property Let GeometryPoint_Y(ByVal Value As Double)
    This.Base.Y = Value
End Property
Public Property Get GeometryPoint_Y() As Double
    GeometryPoint_Y = This.Base.Y
End Property

Public Property Let GeometryPoint_Z(ByVal Value As Double)
    This.Base.Z = Value
End Property
Public Property Get GeometryPoint_Z() As Double
    GeometryPoint_Z = This.Base.Z
End Property

Public Property Set Points(ByVal Value As Collection)
    Set This.Points = Value
End Property
Public Property Get Points() As Collection
    Set Points = This.Points
End Property

Private Sub Class_Initialize()
    Set This.Base = New GeometryPoint
End Sub

Private Sub Class_Terminate()
    Set This.Base = Nothing
End Sub

In VBA, when you "Implement" a class you need to list all of the members (properties, methods) of that class. In your case you received an error because you didn't list the X,Y,Z properties of the cPoint class that you were implementing. Is the "Curve" class supposed to have X,Y,Z properties as well? If not then you shouldn't implement the Point class. If the Curve class is just a class that stores a collection of Points then your Curve class should look like this:

**Note: This code was edited to include the "Class_Initialize" method which sets the "Points" member as a new collection once the Curve class is instantiated.

Option Explicit

Private Type TState
    ID          As Long
    Points      As Collection
End Type

Private This As TState

Public Property Let ID(ByVal Value As Long)
    This.ID = Value
End Property
Public Property Get ID() As Long
    ID = This.ID
End Property

Public Property Set Points(ByVal Value As Collection)
    Set This.Points = Value
End Property
Public Property Get Points() As Collection
    Set Points = This.Points
End Property

Private Sub Class_Initialize()
    Set This.Points = New Collection
End Sub

Private Sub Class_Terminate()
    Set This.Points = Nothing
End Sub

Finally, adding a new Point object to the "Points" member in the Curve class would look something like this:

Dim NewPoint As GeometryPoint
Dim NewCurve As Curve

Set NewPoint = New GeometryPoint
With NewPoint
    .X = 1
    .Y = 2
    .Z = 3
End With

Set NewCurve = New Curve
With NewCurve.Points
    .Add NewPoint
End With
  • Related