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


当前回答

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

这里有两个例子:

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

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

其他回答

在编程中,数据类型是一种分类,它告诉变量将持有什么类型的值,以及可以对这些值进行哪些数学、关系和逻辑操作而不会出错。

在每种编程语言中,为了尽量减少出错的机会,类型检查都是在程序执行之前或执行过程中进行的。根据类型检查的时间,编程语言有两种类型:静态类型语言和动态类型语言。

也取决于是否发生隐式类型转换,编程语言有两种类型:强类型语言和弱类型语言。

静态类型:

Type checking is done at compile time In source code, at the time of variable declaration, data type of that variable must be explicitly specified. Because if data type is specified in source code then at compile time that source code will be converted to machine code and type checking can happen Here data type is associated with variable like, int count. And this association is static or fixed If we try to change data type of an already declared variable (int count) by assigning a value of other data type (int count = "Hello") into it, then we will get error If we try to change data type by redeclaring an already declared variable (int count) using other data type (boolean count) then also we will get error

int count;         /* count is int type, association between data type
                      and variable is static or fixed */

count = 10;        // no error 
count = 'Hello';   // error 
boolean count;     // error 

由于类型检查和类型错误检测是在编译时完成的,这就是为什么在运行时不需要进一步的类型检查。因此,程序变得更加优化,结果在更快的执行 如果我们想要更严格的代码,那么选择这种类型的语言是更好的选择 例如:Java, C, c++, Go, Swift等。

动态类型:

Type checking is done at runtime In source code, at the time of variable declaration, no need to explicitly specify data type of that variable. Because during type checking at runtime, the language system determines variable type from data type of the assigned value to that variable Here data type is associated with the value assigned to the variable like, var foo = 10, 10 is a Number so now foo is of Number data type. But this association is dynamic or flexible we can easily change data type of an already declared variable (var foo = 10), by assigning a value of other data type (foo = "Hi") into it, no error we can easily change data type of an already declared variable (var foo = 10), by redeclaring it using value of other data type (var foo = true), no error

var foo;            // without assigned value, variable holds undefined data type 

var foo = 10;       // foo is Number type now, association between data 
                    // type and value is dynamic / flexible 
foo = 'Hi';         // foo is String type now, no error 
var foo = true;     // foo is Boolean type now, no error 

由于类型检查和类型错误检测是在运行时完成的,这就是为什么程序变得不那么优化,导致执行速度变慢。尽管如果它们实现了JIT编译器,这些类型的语言的执行速度会更快 如果我们想要轻松地编写和执行代码,那么这种类型的语言是更好的选择,但在这里我们可能会得到运行时错误 例如:Python, JavaScript, PHP, Ruby等。

强类型:

严格维护数据类型相关规则和限制 从一种数据类型到另一种数据类型的转换必须显式进行,不能进行隐式类型转换

# in python, "5" cannot automatically get converted to 5
pybar = "5"

print(10 + pybar)     # error, no `+` operation between `int` and `str` 

类型检查可以在编译时或运行时进行。这意味着强类型语言既可以是静态类型的,也可以是动态类型的 例如:Python, Java, Ruby, c#等。

弱类型:

数据类型相关的规则和限制松散维护 从一种数据类型到另一种数据类型的转换可以隐式进行 如果我们在两个不匹配的数据类型的值之间执行一些操作,那么这种类型的语言可能不会抛出错误。相反,弱类型语言将应用它们自己的隐式类型转换规则,并将返回一些结果

jsbar = "5";

alert(10 + jsbar);  /* "105", no error as javascript implicitly coerces Number 10 
to String "10", so that it can be concatenated with other operand jsbar i.e. "5" */

类型检查可以在编译时或运行时进行。这意味着弱类型语言既可以是静态类型的,也可以是动态类型的 例如:JavaScript, C, c++, PHP等。

从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)。

摘自Addison Wesley,《面向对象的分析与应用设计》,第3期,第66页:

The concepts of strong and weak typing and static and dynamic typing are entirely different. Strong and weak typing refers to type consistency, whereas static and dynamic typing refers to the time when names are bound to types. Static typing (also known as static binding or early binding) means that the types of all variables and expressions are fixed at the time of compilation; dynamic typing (also known as late binding) means that the types of all variables and expressions are not known until runtime. A language may be both strongly and statically typed (Ada), strongly typed yet supportive of dynamic typing (C++, Java), or untyped yet supportive of dynamic typing (Smalltalk).

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

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