Types as Objects
An example of the overloadable operators and member procedures
Description
When a Type structure is used to define a user object, many procedure kinds can also be added to the data field skeleton to simplify its use by any user:
- Sub, Function and Properties members.
- Constructors and Destructor.
- Overload Operators (inside and outside Type definition).
The following example is just a syntactic template for their declarations and definitions:
`
'' Sample Type showing available methods and operators
'' Practically this is a pointless example, as the only
'' data member is an Integer. It serves only as a
'' guide to syntax.
''
'' There are many other combinations that can be
'' used in passed parameters. For simplicity
'' This example only uses byref and type T
'' where ever possible.
'' The type 'DataType' is included to show where
'' any data type might be used
Type DataType As Integer
'' The type 'UDT' is included to show where only
'' a UDT data type can be used
Type UDT
value As DataType
End Type
'' Our main type
Type T
value As DataType
value_array( 0 ) As DataType
'' let, cast, combined assignment operators,
'' constructors, and the destructor, must be
'' declared inside the type.
''
'' Parameters can be passed Byval or Byref
'' in most (All? - verify this).
''
'' All procs can be overloaded with different
'' types as parameters. In many cases this is not
'' necessary as the TYPE can be coerced and
'' converted depending on the CAST methods
'' it exposes. The compiler will to its best
'' to evaluate statements and expressions if
'' there is enough information to complete
'' the operation.
''
'' For example,
'' Even though operator += may not be overloaded
'' but operator let and operator + are, the
'' compiler will convert the T += datatype
'' to T = T + datatype.
'' Nonstatic members must be declared inside the
'' type.
''
'' All Nonstatic members are implicitly
'' passed a hidden **this** parameter having
'' the same type as the TYPE in which they are
'' declared.
''
'' Nonstatic member overloaded operators do not
'' return a type. All operations are done on the
'' hidden this parameter.
''
'' Properties: Can be value properties or single
'' indexed value properties
'' GET/SET methods must be each delcared if used.
'' Nonstatic Member Declarations:
'' Memory Allocation/Deallocation
Declare Operator New ( ByVal size As UInteger ) As Any Ptr
Declare Operator New[] ( ByVal size As UInteger ) As Any Ptr
Declare Operator Delete ( ByVal buf As Any Ptr )
Declare Operator Delete[] ( ByVal buf As Any Ptr )
'' Assignment
Declare Operator Let ( ByRef rhs As T )
Declare Operator Let ( ByRef rhs As DataType )
'' Cast can be overloaded to return multiple types
Declare Operator Cast () As String
Declare Operator Cast () As DataType
'' Combined assignment
Declare Operator += ( ByRef rhs As T )
Declare Operator += ( ByRef rhs As DataType )
Declare Operator -= ( ByRef rhs As DataType )
Declare Operator *= ( ByRef rhs As DataType )
Declare Operator /= ( ByRef rhs As DataType )
Declare Operator \= ( ByRef rhs As DataType )
Declare Operator Mod= ( ByRef rhs As DataType )
Declare Operator Shl= ( ByRef rhs As DataType )
Declare Operator Shr= ( ByRef rhs As DataType )
Declare Operator And= ( ByRef rhs As DataType )
Declare Operator Or= ( ByRef rhs As DataType )
Declare Operator Xor= ( ByRef rhs As DataType )
Declare Operator Imp= ( ByRef rhs As DataType )
Declare Operator Eqv= ( ByRef rhs As DataType )
Declare Operator ^= ( ByRef rhs As DataType )
Declare Operator &= ( ByRef rhs As DataType )
'' Address of
Declare Operator @ () As DataType Ptr
'' Constructors can be overloaded
Declare Constructor ()
Declare Constructor ( ByRef rhs As T )
Declare Constructor ( ByRef rhs As DataType )
'' There can be only one destructor
Declare Destructor ()
'' Nonstatic member functions and subs
'' overloaded procs must have different parameters
Declare Function f ( ) As DataType
Declare Function f ( ByRef arg1 As DataType ) As DataType
Declare Sub s ( )
Declare Sub s ( ByRef arg1 As T )
Declare Sub s ( ByRef arg1 As DataType )
'' Properties
Declare Property p () As DataType
Declare Property p ( ByRef new_value As DataType )
Declare Property pidx ( ByVal index As DataType ) As DataType
Declare Property pidx ( ByVal index As DataType, ByRef new_value As DataType )
'' Iterator
Declare Operator For ()
Declare Operator Step ()
Declare Operator Next ( ByRef cond As T ) As Integer
Declare Operator For ( ByRef stp As T )
Declare Operator Step ( ByRef stp As T )
Declare Operator Next ( ByRef cond As T, ByRef stp As T ) As Integer
End Type
'' These must be global procedures
'' Globals are not prefixed with the the TYPE name
'' At least one parameter must be of Type 'T'
'' For simplicity, type 'T' is always given first for binary ops
'' in this example
Declare Operator - ( ByRef rhs As T ) As DataType
Declare Operator Not ( ByRef rhs As T ) As DataType
Declare Operator -> ( ByRef rhs As T ) As UDT
Declare Operator * ( ByRef rhs As T ) As DataType
Declare Operator + ( ByRef lhs As T, ByRef rhs As DataType ) As DataType
Declare Operator - ( ByRef lhs As T, ByRef rhs As DataType ) As DataType
Declare Operator * ( ByRef lhs As T, ByRef rhs As DataType ) As DataType
Declare Operator / ( ByRef lhs As T, ByRef rhs As DataType ) As DataType
Declare Operator \ ( ByRef lhs As T, ByRef rhs As DataType ) As DataType
Declare Operator Mod ( ByRef lhs As T, ByRef rhs As DataType ) As DataType
Declare Operator Shl ( ByRef lhs As T, ByRef rhs As DataType ) As DataType
Declare Operator Shr ( ByRef lhs As T, ByRef rhs As DataType ) As DataType
Declare Operator And ( ByRef lhs As T, ByRef rhs As DataType ) As DataType
Declare Operator Or ( ByRef lhs As T, ByRef rhs As DataType ) As DataType
Declare Operator Xor ( ByRef lhs As T, ByRef rhs As DataType ) As DataType
Declare Operator Imp ( ByRef lhs As T, ByRef rhs As DataType ) As DataType
Declare Operator Eqv ( ByRef lhs As T, ByRef rhs As DataType ) As DataType
Declare Operator ^ ( ByRef lhs As T, ByRef rhs As DataType ) As DataType
Declare Operator = ( ByRef lhs As T, ByRef rhs As DataType ) As DataType
Declare Operator <> ( ByRef lhs As T, ByRef rhs As DataType ) As DataType
Declare Operator < ( ByRef lhs As T, ByRef rhs As DataType ) As DataType
Declare Operator > ( ByRef lhs As T, ByRef rhs As DataType ) As DataType
Declare Operator <= ( ByRef lhs As T, ByRef rhs As DataType ) As DataType
Declare Operator >= ( ByRef lhs As T, ByRef rhs As DataType ) As DataType
Declare Operator & ( ByRef lhs As T, ByRef rhs As DataType ) As DataType
Declare Operator Abs ( ByRef arg As UDT ) As Double
Declare Operator Fix ( ByRef arg As UDT ) As Double
Declare Operator Frac ( ByRef arg As UDT ) As Double
Declare Operator Int ( ByRef arg As UDT ) As Double
Declare Operator Sgn ( ByRef arg As UDT ) As Double
'' Global procedures (subs and funcs) can also accept the TYPE
'' as a parameter or return it as a value, as could be done
'' in previous versions of FreeBASIC.
'' No example given. See function or sub in the manual.
'' All TYPE members are defined outside the TYPE
'' Nonstatic members must be prefixed with type name
'' in this case 'T'
'' Name resolution in a NAMESPACE is same as other
'' subs/funcs. Use USING or prefix the namespace name
Operator T.new ( ByVal size As UInteger ) As Any Ptr
Operator = Allocate( size )
End Operator
Operator T.new[] ( ByVal size As UInteger ) As Any Ptr
Operator = Allocate( size )
End Operator
Operator T.delete ( ByVal buf As Any Ptr )
Deallocate buf
End Operator
Operator T.delete[] ( ByVal buf As Any Ptr )
Deallocate buf
End Operator
Operator T.let ( ByRef rhs As T )
value = rhs.value
End Operator
Operator T.let ( ByRef rhs As DataType )
value = rhs
End Operator
Operator T.cast ( ) As String
Return Str( value )
End Operator
Operator T.cast ( ) As DataType
Return value
End Operator
Operator T.+= ( ByRef rhs As T )
value += rhs.value
End Operator
Operator T.+= ( ByRef rhs As DataType )
value += rhs
End Operator
Operator T.-= ( ByRef rhs As DataType )
value -= rhs
End Operator
Operator T.*= ( ByRef rhs As DataType )
value *= rhs
End Operator
Operator T./= ( ByRef rhs As DataType )
value /= rhs
End Operator
Operator T.\= ( ByRef rhs As DataType )
value \= rhs
End Operator
Operator T.mod= ( ByRef rhs As DataType )
value Mod= rhs
End Operator
Operator T.shl= ( ByRef rhs As DataType )
value Shl= rhs
End Operator
Operator T.shr= ( ByRef rhs As DataType )
value Shr= rhs
End Operator
Operator T.and= ( ByRef rhs As DataType )
value And= rhs
End Operator
Operator T.or= ( ByRef rhs As DataType )
value Or= rhs
End Operator
Operator T.xor= ( ByRef rhs As DataType )
value Xor= rhs
End Operator
Operator T.imp= ( ByRef rhs As DataType )
value Imp= rhs
End Operator
Operator T.eqv= ( ByRef rhs As DataType )
value Eqv= rhs
End Operator
Operator T.^= ( ByRef rhs As DataType )
value ^= rhs
End Operator
Operator T.&= ( ByRef rhs As DataType )
Dim tmp As String
tmp &= Str( rhs )
End Operator
Operator T.@ () As DataType Ptr
Return( Cast( DataType Ptr, @This ))
End Operator
'' Constructors:
Constructor T ()
'' default constructor
value = 0
End Constructor
Constructor T ( ByRef rhs As T )
'' copy constructor
value = rhs.value
End Constructor
Constructor T ( ByRef rhs As DataType )
'' custom constructor
value = rhs
End Constructor
'' There can be only one destructor
Destructor T ()
'' clean-up, none in this example
End Destructor
'' Globals must specify all arguments and return type
Operator - ( ByRef rhs As T ) As DataType
Return (-rhs.value)
End Operator
Operator Not ( ByRef rhs As T ) As DataType
Return (Not rhs.value)
End Operator
Operator -> ( ByRef rhs As T ) As UDT
Return Type(4)
End Operator
Operator * ( ByRef rhs As T ) As DataType
Return 5
End Operator
Operator + ( ByRef lhs As T, ByRef rhs As DataType ) As DataType
Return (lhs.value + rhs)
End Operator
Operator - ( ByRef lhs As T, ByRef rhs As DataType ) As DataType
Return (lhs.value - rhs)
End Operator
Operator * ( ByRef lhs As T, ByRef rhs As DataType ) As DataType
Return (lhs.value * rhs)
End Operator
Operator / ( ByRef lhs As T, ByRef rhs As DataType ) As DataType
Return (lhs.value / rhs)
End Operator
Operator \ ( ByRef lhs As T, ByRef rhs As DataType ) As DataType
Return (lhs.value \ rhs)
End Operator
Operator Mod ( ByRef lhs As T, ByRef rhs As DataType ) As DataType
Return (lhs.value Mod rhs)
End Operator
Operator Shl ( ByRef lhs As T, ByRef rhs As DataType ) As DataType
Return (lhs.value Shl rhs)
End Operator
Operator Shr ( ByRef lhs As T, ByRef rhs As DataType ) As DataType
Return (lhs.value Shr rhs)
End Operator
Operator And ( ByRef lhs As T, ByRef rhs As DataType ) As DataType
Return (lhs.value And rhs)
End Operator
Operator Or ( ByRef lhs As T, ByRef rhs As DataType ) As DataType
Return (lhs.value Or rhs)
End Operator
Operator Xor ( ByRef lhs As T, ByRef rhs As DataType ) As DataType
Return (lhs.value Xor rhs)
End Operator
Operator Imp ( ByRef lhs As T, ByRef rhs As DataType ) As DataType
Return (lhs.value Imp rhs)
End Operator
Operator Eqv ( ByRef lhs As T, ByRef rhs As DataType ) As DataType
Return (lhs.value Eqv rhs)
End Operator
Operator ^ ( ByRef lhs As T, ByRef rhs As DataType ) As DataType
Return (lhs.value ^ rhs)
End Operator
Operator = ( ByRef lhs As T, ByRef rhs As DataType ) As DataType
Return (lhs.value = rhs)
End Operator
Operator <> ( ByRef lhs As T, ByRef rhs As DataType ) As DataType
Return (lhs.value <> rhs)
End Operator
Operator < ( ByRef lhs As T, ByRef rhs As DataType ) As DataType
Return (lhs.value < rhs)
End Operator
Operator > ( ByRef lhs As T, ByRef rhs As DataType ) As DataType
Return (lhs.value > rhs)
End Operator
Operator <= ( ByRef lhs As T, ByRef rhs As DataType ) As DataType
Return (lhs.value <= rhs)
End Operator
Operator >= ( ByRef lhs As T, ByRef rhs As DataType ) As DataType
Return (lhs.value >= rhs)
End Operator
Operator & ( ByRef lhs As T, ByRef rhs As DataType ) As DataType
Return Val(lhs.value & rhs)
End Operator
Operator Abs ( ByRef arg As UDT ) As Double
Return Abs(arg.value)
End Operator
Operator Fix ( ByRef arg As UDT ) As Double
Return Fix(arg.value)
End Operator
Operator Frac ( ByRef arg As UDT ) As Double
Return Frac(arg.value)
End Operator
Operator Int ( ByRef arg As UDT ) As Double
Return Int(arg.value)
End Operator
Operator Sgn ( ByRef arg As UDT ) As Double
Return Sgn(arg.value)
End Operator
'' Nonstatic member methods
Function T.f ( ) As DataType
Dim x As DataType
Return x
End Function
Function T.f ( ByRef arg1 As DataType ) As DataType
arg1 = this.value
Return value
End Function
Sub T.s ( )
'' refer to the type using
'' with block
With This
.value = 1
End With
'' field access
this.value = 2
'' directly
value = 3
End Sub
Sub T.s ( ByRef arg1 As T )
value = arg1.value
End Sub
Sub T.s ( ByRef arg1 As DataType )
value = arg1
End Sub
Property T.p () As DataType
'' GET property
Return value
End Property
Property T.p ( ByRef new_value As DataType )
'' SET property
value = new_value
End Property
Property T.pidx ( ByVal index As DataType ) As DataType
'' GET indexed property
Return value_array( index )
End Property
Property T.pidx ( ByVal index As DataType, ByRef new_value As DataType )
'' SET indexed property
value_array( index ) = new_value
End Property
Operator T.for ()
End Operator
Operator T.step ()
End Operator
Operator T.next ( ByRef cond As T ) As Integer
Return 0
End Operator
Operator T.for ( ByRef stp As T )
End Operator
Operator T.step ( ByRef stp As T )
End Operator
Operator T.next ( ByRef cond As T, ByRef stp As T ) As Integer
Return 0
End Operator
'' new, delete, delete[]
'' Allocate object
Dim X As T Ptr = New T
'' Deallocate object
Delete X
'' Allocate object vector
Dim Xlist As T Ptr = New T[10]
'' Deallocate object vector
Delete[] Xlist
`
See also

- `Type`