静态/动态类型和强/弱类型之间的区别是什么?


当前回答

我认为其他同事做得很好,特别是解释了静态类型和动态类型的区别。但就强类型和弱类型而言,应该说都有 不同的理解/观点。

这里有两个例子:

有人说Haskell是强类型的,因为不允许进行任何类型转换。 其他人(例如Dario的观点)说,允许有意地从字符串隐式转换为数字的语言是弱类型的,但甚至其他人称之为鸭子类型。

这两种说法强调的不是类型系统的两个极端,而是完全不同的方面。因此,我同意Ramsey先生的观点,不要用“强”和“弱”来区分类型系统。

其他回答

静态/动态类型是关于获取类型信息的时间(在编译时或在运行时) 强/弱类型是关于如何严格区分类型(例如,语言是否试图进行从字符串到数字的隐式转换)。

更多详细信息请参见维基页面。

从Scott的《编程语言语用学》第3版291页,我们有

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.

因此,简单来说,静态/动态类型指的是发生类型检查的时间:静态类型是编译时间,动态语言是运行时间。类似地,强/弱类型指的是一种语言在强制执行其类型系统时的积极程度。

我试着把斯科特的描述翻译成一个漂亮的图表,我贴在下面。

弱类型意味着对象的类型可以根据上下文而改变。例如,在弱类型语言中,字符串“123”如果添加另一个数字,可能会被视为数字123。具有弱类型的语言示例有bash、awk和PHP。

另一种弱类型语言是C语言,其中内存地址上的数据可以通过强制转换被视为不同的类型。

在强类型语言中,对象的类型不会改变——int始终是int,试图将其用作字符串将导致错误。Java和Python都是强类型的。

动态类型和静态类型之间的区别在于类型规则何时被强制执行。在静态类型语言中,每个变量和参数的类型都必须在源代码中声明,并在编译时强制执行。在动态类型语言中,类型只在运行时使用时进行检查。Java是静态类型,Python是动态类型。

然而,界限有时会有点模糊。例如,尽管Java是静态类型的,但每次你使用反射或强制转换(例如,当使用对象容器时),你都将类型检查推迟到运行时。

类似地,大多数强类型语言仍然会在整数和浮点数之间自动转换(在某些语言中是任意精确的bigint)。

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.

随着时间的推移,强类型语言的实现经常会出现漏洞,通常是为了让运行时系统的一部分可以用高级语言实现。例如,Objective Caml有一个叫做Obj的函数。Magic,它具有简单地返回其参数的运行时效果,但在编译时它将任何类型的值转换为任何其他类型的值。我最喜欢的例子是Modula-3,它的设计者称其类型转换结构为漏洞。

话虽如此,你不能指望任何两个人以完全相同的方式使用“强”和“弱”这个词。所以要避开它们。

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.

静态类型语言和动态类型语言的元素可以组合。例如,c#既支持静态类型变量,也支持动态类型变量,而面向对象语言通常支持类型层次结构的向下转换。静态类型语言通常提供各种绕过类型检查的方法,例如使用强制转换、反射和动态调用。

强类型和弱类型指的是语言在多大程度上试图防止由于使用变量而导致的错误,就好像它是一种类型,而实际上它是另一种类型。例如,C和Java都是静态类型语言,但是Java使用了比C强大得多的类型检查。下面的C代码很容易编译和运行,并会在运行时将一个随机值放入变量b中,很可能会导致错误:

char *a = "123";
int b = (int)a;

等效的Java代码将产生一个编译错误,这通常是可取的:

String a = "123"
int b = (int)a;