0

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.

Tomalak
  • 332,285
  • 67
  • 532
  • 628
furmanp
  • 3
  • 5
  • Why do you think so? It is VBA though. – furmanp Feb 13 '22 at 13:40
  • What methods/properties of a point do you want a curve to inherit ? Maybe this will help https://stackoverflow.com/questions/19373081/ – CDP1802 Feb 13 '22 at 14:48
  • my general idea is that class cCurve inherits x, y, z, id properties from cPoint (as curve is built from points) and then accordingly same thing with surface, which is built from curves. So in short, 1 Curve has a collection of points, 1 Surface has a collection of Curves. – furmanp Feb 13 '22 at 15:02
  • [This](https://bettersolutions.com/vba/class-modules/object-orientated-programming.htm) might help. – Storax Feb 13 '22 at 18:01

1 Answers1

1

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
jtm84
  • 28
  • 5
  • Thanks! That makes a lot of sense the way you explained it. Indeed, the curve itself does not have X, Y, Z properties. Curves is built out of points, and the points only have those properties. How do I add points to the Curve though? I defined new point and assigned values, created new curve but when I try `curve.Points.Add(point)` I get an error that object doesn't support this property or method. – furmanp Feb 15 '22 at 18:10
  • Alright, I just figured how to do it, Ill post it anyway in case someone may have different problem. I simply tried to assign object of cPoint to a collection of points, thus error. What needs to be done is collection of points has to be created and then assigned to curve.points collection `Set Curve.Points = points_col` – furmanp Feb 15 '22 at 18:43
  • @rolkarz I've edited my original post to include the correct approach for adding points to your Curve class. Hopefully this answers your question. – jtm84 Feb 19 '22 at 20:15
  • @jtm82, thanks for the solution and for the update as well. I finally managed to solve my problem (so I marked your reply as a correct solution). Thanks a ton, your reply opened my eyes widely on this topic. – furmanp Feb 20 '22 at 21:04