Broadly speaking, there are two kinds of programming languages: statically typed languages and dynamically typed languages.
A digression on terminology on programming languages. An “object” is a piece of storage handled by a program. A “variable” is a symbol in the program that may refer to an object (otherwise it is “null”). An object may have zero or more variables referring to it. An object may contain other objects. An object may refer to other objects. An object may be referenced by zero or more variables and by zero or more objects. An object that is referenced by no objects and no variables may be a temporary object or an unreachable object. Unreachable objects that are not reclaimed by a reference counting or garbage collection mechanism are memory leaks.
In addition to be created and destroyed, objects are subject of operations in the source code program.
The “type” of an object is the set of operations that may be applied to that object, together we the effect (or “semantics”) or such operations.
For example, we say that an object is of type “number” because we can add 1 to that object, and we say that an object is of type “image” because we can display it on the screen.
In a dynamically typed language variables do not have a type, but objects have. Any allowed operation may be applied to any variable, with undefined semantics. At run-time, it is checked which is the object referenced by the variable. If that variable do not reference any object (i.e. it is null) or if it refers to an object that cannot handle that operation, the run-time support raises a run-time error. Such error usually may be handled by the program itself, and therefore it does not necessarily terminates the program.
If the referenced object handles that operation, the operation is applied to that object producing the effect specific of that type of object.
For example, the following operation:
a + b
if the variable “a” refers to the number 14 and the variable “b” refers to the number 3, gives the number 17; but if the variable “a” refers to the string “14” and the variable “b” refers to the string “3”, gives the string “143”.
Instead, in a statically typed language, it is (almost) always easily inferable which operations are allowed on a non-null variable, that is on the object referenced by such variable. This is because every variable has a static type, that is a type determined before running the program. There is still a partly dynamic typing linked to object-orientation; this is the fact that although a variable has a static type, at run-time it may refer to a subclass of such type, meaning that its allowed operations may have a different semantics according to the actual run-time type of the referenced object.
Therefore, in dynamically typed languages the variables have no own type, and only the objects have a type, while in statically typed languages the variables have a specific type, and the type of the objects (normally) is the same of the variables that refer to them, or it is a type derived from that.
In statically typed languages, the expression in which a variables is used for the first time it is given a type. Actually quite often such statement is just a declaration whose purpose it to define a variable and assign a type to such variable. But often in the same statement an object with an initial value is assigned to that variable, an sometimes such initialization is a quite complex routine. It is also possible never declare explicitly a type, but declare that the type is the same of another expression, or that is type is to be inferred from the value of the initialization statement.
A secondary usage of the declaration of variable in statically typed languages is that is a variable is mistakenly written in some places in a way and in some others in another way, that is if there are typos, the compiler catches them as there is only one declaration and therefore only one allowed identifier.
In dynamically typed languages there is no need to assign a type to a variable, but it is still useful to declare variables to avoid uncaught typos. Actually, if a variable is created the first time it is used, it is too easy to write the following code:
a1 = 3 b = al + 1
and to believe that the object referenced by the “b” variable is the number 4.
Instead, the first statement uses the variable “a1” (A-one), while the second “al” (A-L). Too bad they looked so similar. If every variable had to be declared before its use, that error would haven’t been overlooked. Some dynamically typed languages, like Smalltalk, wisely force to declare every variable, even if no type is assigned to them. Other languages instead have the despicable feature of not requiring such declarations.