Enigma #21, force 3
Simulation of a 'dynamic cast' operator, by using a macro.
(may be interesting for those who want use a kind of polymorphism but not through virtual member procedures, and who do not prefer to call directly the operator 'IS' whose use is not intuitive)
Challenge:
By only defining one code line in the macro body (a somewhat complex line inside the dedicated zone for line insertion ), make so that program works and correctly displays the types/super-types ('IS-A' typename) or not ('IS-NOT-A' typename) of the created instance (referred in 3 different ways).
The main specifications of the macro are commented out in the macro header of test code below.
Test code compatible with fbc version >= 0.90.0:
Code: Select all
#macro dynamic_cast (typename, expression)
' macro to simulate a 'dynamic cast' operator:
' - 'typename' and 'expression' must be directly or indirectly derived from 'Object' using 'Extends',
' but not necessarily on the same inheritance branch
' - A 'typename' reference is always provided:
' - a non 'null' reference referring to 'expression', if 'expression' is compatible to 'typename'
' (@reference = @expression)
' - a 'null' reference referring to nothing, otherwise
' (@reference = 0)
'-------------------------------------- zone beginning for insertion of one line ---------------------------------------
'---------------------------------------- zone ending for insertion of one line ----------------------------------------
#endmacro
#macro family(N) '' for testing purpose, macro to define an inheritance branch structure : family # N
Type Parent##N Extends Object
Public:
Declare Property testIfIsA () As String
Private:
Dim As String sy = "- The instance 'IS-A' Parent" & #N
Const As String sn = "- The instance 'IS-NOT-A' Parent" & #N
End Type
Property Parent##N.testIfIsA () As String
Property = Iif(@This, This.sy, Parent##N.sn)
End Property
Type Child##N Extends Parent##N
Public:
Declare Property testIfIsA () As String
Private:
Dim As String sy = "- The instance 'IS-A' Child" & #N
Const As String sn = "- The instance 'IS-NOT-A' Child" & #N
End Type
Property Child##N.testIfIsA () As String
Property = Iif(@This, This.sy, Child##N.sn)
End Property
Type GrandChild##N Extends Child##N
Public:
Declare Property testIfIsA () As String
Private:
Dim As String sy = "- The instance 'IS-A' GrandChild" & #N
Const As String sn = "- The instance 'IS-NOT-A' GrandChild" & #N
End Type
Property GrandChild##N.testIfIsA () As String
Property = Iif(@This, This.sy, GrandChild##N.sn)
End Property
#endmacro
family(1) '' define an inheritance branch : family # 1
family(2) '' define an inheritance branch : family # 2
Print "Simple Child1 instance variable:"
Dim As Child1 c1i
Print dynamic_cast(Parent1 , c1i).testIfIsA
Print dynamic_cast(Child1 , c1i).testIfIsA
Print dynamic_cast(GrandChild1, c1i).testIfIsA
Print dynamic_cast(Parent2 , c1i).testIfIsA
Print dynamic_cast(Child2 , c1i).testIfIsA
Print dynamic_cast(GrandChild2, c1i).testIfIsA
Print
Print "Dereferenced Parent1 object-type pointer that refers to a Child1 instance:"
Dim As Parent1 Ptr pp1c1i = @c1i
Print dynamic_cast(Parent1 , *pp1c1i).testIfIsA
Print dynamic_cast(Child1 , *pp1c1i).testIfIsA
Print dynamic_cast(GrandChild1, *pp1c1i).testIfIsA
Print dynamic_cast(Parent2 , *pp1c1i).testIfIsA
Print dynamic_cast(Child2 , *pp1c1i).testIfIsA
Print dynamic_cast(GrandChild2, *pp1c1i).testIfIsA
Print
Print "Parent1 object-type reference that refers to a Child1 instance:"
Function p1rc1i (Byref c1 As Child1) Byref As Parent1
Return c1
End Function
Print dynamic_cast(Parent1 , p1rc1i(c1i)).testIfIsA
Print dynamic_cast(Child1 , p1rc1i(c1i)).testIfIsA
Print dynamic_cast(GrandChild1, p1rc1i(c1i)).testIfIsA
Print dynamic_cast(Parent2 , p1rc1i(c1i)).testIfIsA
Print dynamic_cast(Child2 , p1rc1i(c1i)).testIfIsA
Print dynamic_cast(GrandChild2, p1rc1i(c1i)).testIfIsA
Print
Sleep
Execution result to be obtained:
Code: Select all
Simple Child1 instance variable:
- The instance 'IS-A' Parent1
- The instance 'IS-A' Child1
- The instance 'IS-NOT-A' GrandChild1
- The instance 'IS-NOT-A' Parent2
- The instance 'IS-NOT-A' Child2
- The instance 'IS-NOT-A' GrandChild2
Dereferenced Parent1 object-type pointer that refers to a Child1 instance:
- The instance 'IS-A' Parent1
- The instance 'IS-A' Child1
- The instance 'IS-NOT-A' GrandChild1
- The instance 'IS-NOT-A' Parent2
- The instance 'IS-NOT-A' Child2
- The instance 'IS-NOT-A' GrandChild2
Parent1 object-type reference that refers to a Child1 instance:
- The instance 'IS-A' Parent1
- The instance 'IS-A' Child1
- The instance 'IS-NOT-A' GrandChild1
- The instance 'IS-NOT-A' Parent2
- The instance 'IS-NOT-A' Child2
- The instance 'IS-NOT-A' GrandChild2
[edit]
Test program modified in order to impose that the macro returns an UDT reference.