Static and Dynamic Typing

From SwinBrain

Values in the computer are binary values, and to the computer all of these values are equal whether they be instructions, numbers, text, et cetera. When programming we want to be able to assign meaning to the values we are working with. To do this we assign types to data. These types and their interactions are controlled by the programming language's Type System. The type system ensures that the operations performed on data values make sense, and deny you the ability to perform operations that make no sense. For example, it is possible to divide 1 by 3 ( 1 / 3 ) but not to divide 1 by "Hello World" (1 / "Hello World"), even though to the computer 3 and "Hello World" are both just binary numbers.

Type checking is a critical part of the Type System. Type checking is the process of ensuring that type constraints are enforced, and can be performed at compile time or at run time. When the types are checked at compile time this is called static typing, when the types are checked at run time this is called dynamic typing.

Type Safety is another feature of Type Systems. A Type System is type safe if its operations restrict you to only performing operations that are valid for the data you are working on.

Static Typing

A statically typed programming language has its type checking performed by the compiler. In static typing the type details are associated with variables not values. The compiler ensures that only valid operations are performed on these variables. This allows many kinds of errors to be detected when the program is compiled, and can result in more efficient code generation as the compiler can take advantage of this type information. Languages like C, C++, C#, Pascal, and Java are statically typed.

Most statically typed languages require that variables be declared with a specified type[1], for example int x;, Drawing x;, var x: String;. This information is then available for the compiler to use for type checking.

To ensure type safety in statically typed languages the compiler needs to be conservative. Only the operations from a variable's declared type are permitted to be performed on the variable, regardless of the actual value at runtime. This will deny any other operation, even in cases where the operation is permitted on the actual type (value) at runtime. For example, a variable Shape s; is assigned a rectangle s = new Rectangle(...);, this is valid as the Rectangle inherits from Shape. Even if the Rectangle class contains the definition for a MakeSquare() method, the code s.MakeSquare(); will be rejected by the compiler as s is a Shape and MakeSquare is not a method available on the Shape class.

For convenience, many statically typed programming languages provide means of converting between data types. These conversion function often result in a Type System that is not Type safe, meaning that some type errors are not detected by the compiler. For example: in C, C# and Java it is possible to cast a value from one type to another. As an example the code s.MakeSquare(); from above failed as s is not a Rectangle, if this is C# code we can make this work using a type cast ((Rectangle)s).MakeSquare(); which can be thought of as telling the compiler that s is a Rectangle. This may, however, result in type errors at runtime. In this case if s is not a Rectangle an error will occur. This error is handled by the C# runtime (a dynamic test) and an exception occurs, thereby ensuring type safety. Had the operation been allowed to success the language would not be type safe.

Dynamic Typing

A dynamically typed programming language has the majority of its type checking performed at run time. In dynamic typing the type details are associated with values and not with variables. As a result most dynamic languages do not require type information[2] when variables are declared, as is typically done with statically typed languages.

Dynamic languages have the advantage of having additional information when the type checking is performed. The language is able to inspect the actual run time value to determine if the operation should be permitted. The Rectangle/Shape issue discussed about cannot occur as the runtime system will be aware that the object is in fact a Rectangle. In this case it is likely that the language is looking to see if the object understands the MakeSquare() method and if it does the message will be passed to the object otherwise an exception will occur indicating that the object does not understand the message[3].

As dynamic languages perform less type checking at compile time, type errors are not found until run time. Unfortunately, these type errors may also be difficult to detect as the source of the error may be distant from the location of the error at runtime. When using a dynamic language testing tools like unit testing become even more important.

Languages like Lua, Objective C, and Python are dynamically typed (often shortened to just 'dynamic').

[edit]Links: Topic Brains
Return to Swin Brain

  1. Type information is not necessarily required with variable declarations even with statically typed languages, as the compiler may be able to infer the type of a variable from its usage. For example, C# 3.0 introduced variable declaration without type information by using the var keyword.
  2. Languages like Objective C allow type information for variable declarations. This allows the compiler to generate warnings (not errors) though the actual type checking (enforcement) is performed at run time.
  3. If a language supports meta language features, it may also be possible for an object to receive alter itself in response to messages it doesn't understand by interacting with the message passing features of the language.