Compile-Time type checking
Strong Type Checking could also be described as “Compile-Time Type Checking”.
CA-Cl*pper generates a Run-Time Error (“Type Mismatch”) at an attempt to perform some operations with the wrong type of Variable.
LOCAL Var1 := "A"
? Var1 * 3 // Error here.
@ Var1, 7 SAY 'Hello' // Error here.
? SubStr( "Hello", Var1 ) // Error here.
The above 3 lines would all result in Run-Time Error, because Var1 is of type CHARACTER but the above lines used it as if it was of type NUMERIC.
Using Strong Type Checking, or Compile-Time Type Checking, the above problem would have been discovered and reported in COMPILE-TIME, rather than waiting for the inevitable problem to be discovered when we finally execute the program.
Strong Typed Languages allow the programmer to “tell” the compiler (declare) what is the type of a each Variable, so that the Compiler in return can warn the programmer, when ever such Declared (Strong Typed) Variable, is used in a context which is incompatible with its declared type.
For instance, if we “told” the compiler that Var1 above is of type CHARACTER (LOCAL Var1 AS CHARACTER) the Harbour Compiler could, in return, warn us if we attempted to perform the calculation:
Var1 * 3
because the Compiler knows we can’t perform a multiplication of a Character. (we might allow it in some context, but this is beyond the scope of this discussion). Similarly we would have been warned when attempting to use Var1 as a Row Number ( @ Var1 ), or as the 2nd operand of the SubStr() function SubStr( “Hello”, Var1) ), because the Compiler knows that these operations require a NUMERIC rather than CHARACTER type.
The above may save us lots of time, by pointing a problem, we can not escape, since such code will never perform correctly once executed. So rather than wait to the testing cycle, for such problems to be discovered, (and some times even later, after we may have distributed our applications) instead we may know of such problems as soon as we type HARBOUR ProgName -w3
Harbour also offers a hybrid mode, where it can report such type mismatch problems, even without requiring the programmer to declare the type of variables. This feature, is referred to as Adaptive Type Checking. The programmer is not required to make any changes in his code to take advantage of this feature. All of the above 3 errors would have been reported just as effectively as if the programmer Strong Typed (declared) Var1. Harbour would have been able to report such problems at compile time because the assignment Var1 := “A” implied that Var1 is of type CHARACTER, until it will be assigned another value. Therefore Harbour will “remember” that Var1 “adapted” type CHARACTER, and thus the subsequent multiplication Var1 * 3, will be reported as an error, as soon as you attempt to compile such code.
The nice aspect of this hybrid mode, is that unlike Strong Typed Variables, you don’t have to declare the type, so no code changes are need, the Type instead is assumed by implication (type of the assigned value). The other benefit, is that it is completely OK to assign a new value of different type, any time, to such undeclared (variant) variable. As soon as we assign a new type, the Compiler will than protect us from using the Variable in an incompatible context, since the variable “adapted” this type as soon as we assigned a value which implies a type.
While Adapted Type Checking may be fairly effective in reporting many common mistakes, to take full benefits of such Compile-Time checking, it is recommended to do declare the Type of Variables, when ever possible.
The Harbour Strong Type features, also allows the declaration of the expected parameters (including optionals) of User Defined Functions, as well as their return Type. Similarly, you may declare the Type of any Class Variables, Methods, and Methods Parameters.