Help Center
Help CenterFreeBASICTutorials

Types as Objects

Documentation

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