I see these terms bandied around all over the place in programming and I have a vague notion of what they mean. A search shows me that such things have been asked all over stack overflow in fact. As far as I'm aware Static/Dynamic typing in languages is subtly different to Strong/Weak typing but what that difference is eludes me. Different sources seem to use different meanings or even use the terms interchangeably. I can't find somewhere that talks about both and actually spells out the difference. What would be nice is if someone could please spell this out clearly here for me and the rest of the world.
Static/Dynamic Typing is about when type information is acquired (Either at compile time or at runtime)
Strong/Weak Typing is about how strictly types are distinguished (e.g. whether the language tries to do an implicit conversion from strings to numbers).
See the wiki-page for more detailed information.
You have discovered a soft spot in the terminology that amateurs use to talk about programming languages. Don't use the terms "strong" and "weak" typing, because they don't have a universally agreed on technical meaning. By contrast, static typing means that programs are checked before being executed, and a program might be rejected before it starts. Dynamic typing means that the types of values are checked during execution, and a poorly typed operation might cause the program to halt or otherwise signal an error at run time. A primary reason for static typing is to rule out programs that might have such "dynamic type errors".
Strong typing generally means that there are no loopholes in the type system, whereas weak typing means the type system can be subverted (invalidating any guarantees). The terms are often used incorrectly to mean static and dynamic typing. To see the difference, think of C: the language is type-checked at compile time (static typing), but there are plenty of loopholes; you can pretty much cast a value of any type to another type of the same size---in particular, you can cast pointer types freely. Pascal was a language that was intended to be strongly typed but famously had an unforeseen loophole: a variant record with no tag.
Implementations of strongly typed languages often acquire loopholes over time, usually so that part of the run-time system can be implemented in the high-level language. For example, Objective Caml has a function called Obj.magic
which has the run-time effect of simply returning its argument, but at compile time it converts a value of any type to one of any other type. My favorite example is Modula-3, whose designers called their type-casting construct LOOPHOLE
.
Having said that, you can't count on any two people using the words "strong" and "weak" in exactly the same way. So avoid them.
Simply put it this way: in a statically typed language the type is static, meaning once you set a variable to a type, you CANNOT change it. That is because typing is associated with the variable rather than the value it refers to.
For example in Java:
String str = "Hello"; //statically typed as string
str = 5; //would throw an error since java is statically typed
Whereas in a dynamically typed language the type is dynamic, meaning after you set a variable to a type, you CAN change it. That is because typing is associated with the value rather than the variable.
For example in Python:
str = "Hello" # it is a string
str = 5 # now it is an integer; perfectly OK
On the other hand, the strong/weak typing in a language is related to implicit type conversions (partly taken from @Dario's answer):
For example in Python:
str = 5 + "hello"
# would throw an error since it does not want to cast one type to the other implicitly.
whereas in PHP:
$str = 5 + "hello"; // equals 5 because "hello" is implicitly casted to 0
// PHP is weakly typed, thus is a very forgiving language.
Static typing allows for checking type correctness at compile time. Statically typed languages are usually compiled, and dynamically typed languages are interpreted. Therefore, dynamicly typed languages can check typing at run time.
Weak typing means that the type of an object can change depending on context. For example in a weakly typed language the string "123" may be treated as the number 123 if you add another number to it. Examples of languages with weak typing are bash, awk and PHP.
Another kind of weakly typed language is C, where the data at a memory address can be treated as a different type by casting.
In a strongly typed language the type of an object does not change - an int is always an int and trying to use it as a string will result in an error. Both Java and Python are strongly typed.
The difference between dynamic and static typing is when the type rules are enforced. In a statically typed language the type of every variable and parameter must be declared in the source and is enforced at compile time. In a dynamically typed language the types are only checked when they are used at runtime. So Java is statically typed and Python is dynamically typed.
However the boundaries can be a little blurry at times. For example although Java is statically typed, every time you use reflection or a cast (e.g. when using containers of Objects) they you are deferring the type check to runtime.
Similarly most strongly typed languages will still automatically convert between integers and floats (and in some languages abitrary precision BigInts).
Today researching about this subject I came across this great article http://blogs.perl.org/users/ovid/2010/08/what-to-know-before-debating-type-systems.html It cleared up a lot of things for me and I thought It may add to some of the great answers above.
Strong and Weak Typing:
Probably the most common way type systems are classified is "strong" or "weak." This is unfortunate, since these words have nearly no meaning at all. It is, to a limited extent, possible to compare two languages with very similar type systems, and designate one as having the stronger of those two systems. Beyond that, the words mean nothing at all.
Static and Dynamic Types
This is very nearly the only common classification of type systems that has real meaning. As a matter of fact, it's significance is frequently under-estimated [...] Dynamic and static type systems are two completely different things, whose goals happen to partially overlap.
A static type system is a mechanism by which a compiler examines source code and assigns labels (called "types") to pieces of the syntax, and then uses them to infer something about the program's behavior. A dynamic type system is a mechanism by which a compiler generates code to keep track of the sort of data (coincidentally, also called its "type") used by the program. The use of the same word "type" in each of these two systems is, of course, not really entirely coincidental; yet it is best understood as having a sort of weak historical significance. Great confusion results from trying to find a world view in which "type" really means the same thing in both systems. It doesn't.
Explicit/Implicit Types:
When these terms are used, they refer to the extent to which a compiler will reason about the static types of parts of a program. All programming languages have some form of reasoning about types. Some have more than others. ML and Haskell have implicit types, in that no (or very few, depending on the language and extensions in use) type declarations are needed. Java and Ada have very explicit types, and one is constantly declaring the types of things. All of the above have (relatively, compared to C and C++, for example) strong static type systems.
From Scott's Programming Language Pragmatics, 3rd edition page 291, we have
Type checking is the process of ensuring that a program obeys the language’s type compatibility rules. A violation of the rules is known as a type clash. A language is said to be strongly typed if it prohibits, in a way that the language implementation can enforce, the application of any operation to any object that is not intended to support that operation. A language is said to be statically typed if it is strongly typed and type checking can be performed at compile time. In the strictest sense of the term, few languages are statically typed. In practice, the termis often applied to languages in which most type checking can be performed at compile time, and the rest can be performed at run time.
A few examples: Ada is strongly typed, and for the most part statically typed (certain type constraints must be checked at run time). A Pascal implementation can also do most of its type checking at compile time, though the language is not quite strongly typed: untagged variant records (to be discussed in Section 7.3.4) are its only loophole. C89 is significantly more strongly typed than its predecessor dialects, but still significantly less strongly typed than Pascal. Its loopholes include unions, subroutineswith variable numbers of parameters, and the interoperability of pointers and arrays (to be discussed in Section 7.7.1). Implementations of C rarely check anything at run time.
Dynamic (run-time) type checking is a form of late binding, and tends to be found in languages that delay other issues until run time as well. Lisp and Smalltalk are dynamically (though strongly) typed. Most scripting languages are also dynamically typed; some (e.g., Python and Ruby) are strongly typed. Languages with dynamic scoping are generally dynamically typed (or not typed at all): if the compiler can’t identify the object to which a name refers, it usually can’t determine the type of the object either.
So in simple terms, static/dynamic typing refers to the time when type checking occurs: compile time for static typing, and run time for dynamic languages. Likewise, strong/weak typing refers to how aggressive a language is in enforcing its type system.
I've tried to translate Scott's description into a nice diagram, which I've posted below.
I think the other colleagues made a good job esp. explaining the difference between static and dynamic typing. But as far as strong and weak typing is concerned, it should be said that there are different understandings/views.
Here two examples:
Some say that Haskell is strongly typed, because you are not allowed to make any type conversions.
Others (e.g. Dario's view) say a language that allows to implicitly convert from string to number on purpose is weakly typed, but even others call this just duck typing.
Both statements highlight not the opposite extremes of a type system, but completely different aspects. So I join Mr. Ramsey's view not to use the terms "strong" and "weak" to distinguish between type systems.
Statically v/s dynamically typed languages
- Statically typed languages are those in which type checking is done at the compile time, so this also means that in statically typed languages each variable has a type and it doesn’t change over the course. Now, in contrast, dynamically typed languages are those in which type checking is done at runtime, and there is no type checking at compile time, so this also means that in dynamically typed languages there may or may not be a type associated with a variables, and if a type is associated then it could be a generic type like “var” in JS which hold good for both a string and number.
- “Implementations of dynamically type-checked languages generally associate each runtime object with a type tag (i.e., a reference to a type) containing its type information. This runtime type information (RTTI) can also be used to implement dynamic dispatch, late binding, down casting, reflection, and similar features.”
- Even if language is statically typed, still it could have some dynamically typed feature, which basically means that some sort of type checking at runtime as well. This is useful in casting of types.
- “A number of useful and common programming language features cannot be checked statically, such as down casting. Thus, many languages will have both static and dynamic type checking; the static type checker verifies what it can, and dynamic checks verify the rest.”
- “Some languages allow writing code that is not type-safe. For example, in C, programmers can freely cast a value between any two types that have the same size.”
- Advantage of “statically” typed languages are that:
- Since most of the type checking is done at compile time so interpreter or runtime can run at full speed, without worrying about the types.
- It leads to lesser number of runtime exception or errors related to type, because most of the type checking is done at compile time.
- Advantage of “dynamically” typed languages are that:
- They could help in extremely fast prototyping, since developer need not to understand the type system so dev can loosely create variables and run it, and this leads to very fast prototyping.
- List of statically and dynamically typed languages:
- Statically:
- Java
- C (C is a statically typed language but lesser “strongly” typed as compared to Java because it allows more implicit conversions)
- C++
- C#
- Dynamically:
- PERL
- PHP
- Python
- JavaScript
- Ruby
- Statically:
- Type checking is an important security feature. Suppose, there is no type checking, and a method accepts an object of type “BankAccount” which has a method called as “creditAccount(BankAccountDetails)”, now at runtime if there is no type checking then I can pass an object of my own class which has same method “creditAccount(BankAccountDetails)” and it will get executed, considering we are talking about object oriented language because OOP supports “polymorphism” and here what we are discussing is nothing but “polymorphism”. So, basically an object oriented language (which basically means it supports “polymorphism”) which doesn’t have strong type checking can lead to security issues.
Strongly v/s weakly typed languages
- Strongly typed languages are those in which implicit conversions are not allowed if there is loss of precision. For example, in Java, you can cast an “int to long” because there is no loss of precision but you cannot “implicitly” cast a “long to int” because there would be loss of precision. In contrast, in weakly typed languages, implicit conversions are allowed even if there is loss of precision.
- I think dynamically typed language can also be a strongly typed language if “at runtime” it doesn’t allow implicit conversions in which there is loss of precision.
Good further readings
Statically typed languages generally require you to declare the types of variables, which is then checked at compile time to reduce errors. The word "static" in "statically typed" refers to "static code analysis", which is the process of examining the code prior to executing it. Although it is possible for a statically typed language to infer the type of the variable from the right hand side of an expression or actual parameters, in practice most statically typed languages require variable types to be explicitly declared.
Dynamically typed languages generally do not require variable declarations to have types, and they infer variable types based on the type calculated as a result of evaluating the right hand side of every assignment statement or the actual parameters to a function call. Since the variable can be given multiple assignments over its lifetime, its type can change over time and this is why it is called "dynamically typed". Also, the runtime environment needs to keep track of the current type for each variable, so the type is bound to the value rather than with the variable declaration. This can be considered a runtime type information (RTTI) system.
Elements of statically and dynamically typed languages can be combined. For example, C# supports both statically and dynamically typed variables, and object oriented languages generally support down-casting the type hierarchy. Statically typed languages usually provide various ways to bypass type checking, for example by using casting, reflection and dynamic invocation.
Strong vs. Weak Typing refers to a continuum of how much the language tries to prevent bugs due to using a variable as if it were one type when it is in fact another type. For example both C and Java are statically typed languages, however Java uses much stronger type checking than does C. The following C code is happy to compile and run, and will put a random value into the variable b at runtime, most likely causing a bug:
char *a = "123";
int b = (int)a;
The equivalent Java code will produce a compile error, which is generally preferable:
String a = "123"
int b = (int)a;
I recently wrote an article explaining this exact topic:
https://dev.to/jiangh/type-systems-dynamic-versus-static-strong-versus-weak-b6c
来源:https://stackoverflow.com/questions/2351190/static-dynamic-vs-strong-weak