I am working an a more meaningful way to print objects in VBA. The desired result should look something like this.
Console.PrintLine List.Create(1, 2, 3)
List(1, 2, 3)
The concept is that objects implementing an IPrintable
interface are printed as their ToString
property. Primitive data types are printed as is
Console.PrintLine "a"
a
And other objects are represented as "TypeName(&ObjPtr)"
Console.PrintLine New Collection
Collection(&150653720)
But the issue that is gunking up my design is that I want nested objects to represent themselves
Console.PrintLine List.Create(1, List.Create(), New Collection)
List(1, List(), Collection(&150653384))
My solution is to use an auxiliary helper methods, located in a standard module called cast
, which in a way provides a default implementation of IPrintable
Public Function ToString(ByVal x As Variant) As String
Dim result As String
If TypeOf x Is IPrintable Then
result = x.ToString
ElseIf IsObject(x) Then
result = DefaultObjectToString(x)
Else
result = CStr(x)
End If
ToString = result
End Function
Private Function DefaultObjectToString(ByVal x As Object) As String
DefaultObjectToString = ObjectToString(x, cast.CArray(Array("&" & ObjPtr(x))))
End Function
Public Function ObjectToString(ByVal o As Object, ByRef members() As Variant, _
Optional ByVal delim As String = ", ") As String
Dim stringMembers() As String
If LBound(members) <= UBound(members) Then
ReDim stringMembers(LBound(members) To UBound(members))
End If
Dim i As Long
For i = LBound(members) To UBound(members)
stringMembers(i) = ToString(members(i))
Next i
ObjectToString = TypeName(o) & "(" & Join(stringMembers, delim) & ")"
End Function
I would want this to be located in the IPrintable
class but that must be empty to use it as an interface.
Now any method that is printing the objects can just use cast.ToString
like console does
Public Sub PrintLine(Optional ByVal x As Variant)
If IsMissing(x) Then
Debug.Print vbNullString
Else
Debug.Print cast.ToString(x)
End If
End Sub
Also here is how List
implements IPrintable
(ToArray
is just an array version of the list.)
Public Property Get ToString(Optional delim As String = ", ") As String
ToString = cast.ObjectToString(Me, ToArray, delim)
End Property
Public Property Get IPrintable_ToString() As String
IPrintable_ToString = ToString()
End Property
If I had a BinaryTree object it would look like this.
Public Property Get ToString() As String
ToString = cast.ObjectToString(Me, Array(LeftTree, RightTree), ", ")
End Property
Cast
to be a class? – RubberDuck Feb 4 '15 at 2:01cast
is a standard module not a class. I will update the post to specify – cheezsteak Feb 4 '15 at 14:48Cast
module! – Mat's Mug♦ Feb 4 '15 at 15:20