静态/动态与强/弱

时间:2010-02-28 13:42:22

标签: terminology strong-typing static-typing dynamic-typing weak-typing

我看到这些术语在编程中遍布各地,我对它们的含义有一个模糊的概念。搜索显示,事实上,这些事情已被问到堆栈溢出。据我所知,语言中的静态/动态类型与强/弱类型略有不同,但这种差异是我的意思。不同的来源似乎使用不同的含义甚至可以互换地使用这些术语。我找不到谈论两者的地方,实际上说明了差异。如果有人可以在这里为我和世界其他地方清楚地说明这一点,那会更好。

11 个答案:

答案 0 :(得分:377)

  • 静态/动态打字是关于获取类型信息时(编译时或运行时)

  • 强/弱打字是关于如何区分严格类型(例如,语言是否尝试从字符串到数字进行隐式转换)。

有关更多详细信息,请参阅wiki-page

答案 1 :(得分:195)

你发现业余爱好者用来谈论编程语言的术语情有独钟。 请勿使用“强”和“弱”字词,因为它们没有普遍认同的技术含义。相比之下,静态类型意味着程序在执行之前检查,并且程序在启动之前可能会被拒绝。 动态类型表示在执行期间检查 的类型,并且类型不佳的操作可能会导致程序停止或以其他方式在运行时发出错误信号。静态类型的主要原因是排除可能具有此类“动态类型错误”的程序。

强类型通常意味着类型系统中存在无漏洞,而弱类型表示类型系统可能被破坏(无效)任何保证)。这些术语经常被错误地用于表示静态和动态类型。 为了看到差异,想想C:语言在编译时被类型检查(静态类型),但是存在很多漏洞;你几乎可以将任何类型的值转换为相同大小的另一种类型 - 特别是,你可以自由地转换指针类型。 Pascal是一种旨在强类型的语言,但却有一个无法预料的漏洞:一个没有标记的变体记录。

强类型语言的实现通常会随着时间的推移而产生漏洞,通常是因为部分运行时系统可以用高级语言实现。例如,Objective Caml有一个名为Obj.magic的函数,它具有简单地返回其参数的运行时效果,但在编译时它将任何类型的值转换为任何其他类型的值。我最喜欢的例子是Modula-3,其设计师称他们的类型转换构造LOOPHOLE

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

答案 2 :(得分:62)

简单地说就是这样:在静态类型语言中,类型是 static ,这意味着一旦将变量设置为类型,就无法更改它。这是因为输入与变量相关联而不是它所引用的值。

例如在Java中:

String str = "Hello";  //statically typed as string
str = 5;               //would throw an error since java is statically typed

动态类型语言中,类型是动态,这意味着在将变量设置为类型后,您可以更改它。这是因为打字与值而不是变量相关联。

例如在Python中:

str = "Hello" # it is a string
str = 5       # now it is an integer; perfectly OK

另一方面,语言中的强/弱类型与隐式类型转换有关(部分取自@Dario的答案):

例如在Python中:

str = 5 + "hello" 
# would throw an error since it does not want to cast one type to the other implicitly. 

而在PHP中:

$str = 5 + "hello"; // equals 5 because "hello" is implicitly casted to 0 
// PHP is weakly typed, thus is a very forgiving language.

静态类型允许在编译时检查类型的正确性。通常编译静态类型语言,并解释动态类型语言。因此,动态类型语言可以在运行时检查键入。

答案 3 :(得分:19)

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

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

在强类型语言中,对象的类型不会改变 - int总是一个int,并且尝试将其用作字符串将导致错误。 Java和Python都是强类型的。

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

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

类似地,大多数强类型语言仍然会自动在整数和浮点数之间进行转换(在某些语言中也会自动转换为精确的BigInts)。

答案 4 :(得分:13)

今天研究这个主题我发现了这篇伟大的文章http://blogs.perl.org/users/ovid/2010/08/what-to-know-before-debating-type-systems.html它为我清理了很多东西,我认为这可能会增加上面的一些重要答案。

强劲而微弱的打字:

  

可能最常见的类型系统被分类为“强”   或“弱”。这是不幸的,因为这些话几乎没有   意思是什么。在有限的程度上,可以比较两个   具有非常相似类型系统的语言,并将其指定为具有   这两个系统中的强者。除此之外,这些词语毫无意义   一点都不。

静态和动态类型

  

这几乎是类型系统的唯一常见分类   这有真正的意义。事实上,它的意义是   经常低估[...]动态和静态类型系统   两个完全不同的东西,其目标部分发生   重叠。

     

静态类型系统是编译器检查的机制   源代码并将标签(称为“类型”)分配给   语法,然后使用它们来推断程序的某些内容   行为。动态类型系统是编译器的一种机制   生成代码以跟踪数据类型(巧合的是,也是如此)   称为程序使用的“类型”。使用相同的单词   当然,这两个系统中的每一个中的“类型”并非完全如此   巧合;但它最好被理解为有一种弱点   历史意义。试图找到一个很大的混乱   世界观中“类型”在两者中的含义都是一样的   系统。它没有。

明确/隐含类型:

  

当使用这些术语时,它们指的是a的程度   编译器将推断程序的静态类型。所有   编程语言对类型有某种形式的推理。一些   比其他人更多。 ML和Haskell有隐式类型,没有   (或极少数,取决于使用的语言和扩展名)类型   声明是必要的。 Java和Ada有非常明确的类型,和   一个人不断宣布事物的类型。所有以上都有   (相对于C和C ++,例如)强静态类型   系统

答案 5 :(得分:6)

我们从Scott的 Programming Language Pragmatics (第三版第291页)中获得了

  

类型检查是确保程序遵守以下规定的过程:   语言的类型兼容性规则。违反规则是众所周知的   作为类型冲突。如果一种语言被称为强输入   以语言实现可以强制执行的方式禁止   将任何操作应用于不希望用于   支持该操作。如果一种语言被称为静态键入   它是强类型的,可以在编译时执行类型检查   时间。从最严格的意义上讲,很少有语言是静态的   输入。实际上,该术语通常适用于以下语言   大多数类型检查可以在编译时执行,其余的可以   在运行时执行。

     

一些例子:Ada是强类型的,并且在大多数情况下   静态类型(必须在运行时检查某些类型约束   时间)。 Pascal实现也可以执行大多数类型检查   在编译时,尽管语言不是很强类型:   未标记的变体记录(将在第7.3.4节中讨论)是其   只有漏洞。 C89的打字性明显强于其   前身的方言,但打字强度仍然明显低于   帕斯卡。它的漏洞包括并集,带有可变数字的子例程   参数以及指针和数组的互操作性   在7.7.1节中讨论)。 C的实现很少检查   在运行时执行任何操作。

     

动态(运行时)类型检查是后期绑定的一种形式,并且倾向于   可以在延迟其他问题直到运行时间的语言中找到   好。 Lisp和Smalltalk是动态(尽管很强)类型的。最   脚本语言也可以动态输入;一些(例如Python和   Ruby)是强类型的。具有动态作用域的语言通常是   动态输入(或根本不输入):如果编译器不能   识别名称所指的对象,通常无法确定   对象的类型。

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

我试图将Scott的描述翻译成一个漂亮的图表,下面将其发布。

The Static/Dynamic - Strong/Weak Typing Plane

答案 6 :(得分:5)

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

这里有两个例子:

  • 有人说Haskell是强类型的,因为你不允许进行任何类型的转换。

  • 其他人(例如Dario的观点)说,一种允许隐含地从字符串转换为数字的语言是弱类型的,但即使是其他人也称这只是打字。

两种陈述都强调不是类型系统的相反极端,而是完全不同的方面。因此,我加入拉姆齐先生的观点,不要使用“强”和“弱”这两个术语来区分类型系统。

答案 7 :(得分:3)

静态v / s动态类型语言

  • 静态类型语言是在编译时进行类型检查的语言,因此这也意味着在静态类型语言中,每个变量都有一个类型,并且在整个过程中不会发生变化。现在,相比之下,动态类型语言是那些在运行时进行类型检查的语言,并且在编译时没有类型检查,所以这也意味着在动态类型语言中可能有也可能没有关联的类型使用变量,如果一个类型被关联,那么它可以是JS中的“var”这样的泛型类型,它对字符串和数字都有好处。
    • “动态类型检查语言的实现通常将每个运行时对象与包含其类型信息的类型标记(即,对类型的引用)相关联。此运行时类型信息(RTTI)还可用于实现动态分派,后期绑定,向下转换,反射和类似功能。“
  • 即使语言是静态类型的,它仍然可以有一些动态类型的功能,这基本上意味着在运行时也会进行某种类型的检查。这在类型的转换中很有用。
    • “无法静态检查许多有用且常用的编程语言功能,例如向下转换。因此,许多语言都将进行静态和动态类型检查;静态类型检查器验证它可以做什么,动态检查验证其余部分。“
  • “某些语言允许编写非类型安全的代码。例如,在C语言中,程序员可以在任何两种具有相同大小的类型之间自由地转换值。“
  • “静态”类型语言的优点在于:
    • 由于大多数类型检查都是在编译时完成的,因此解释器或运行时可以全速运行,而不必担心类型。
    • 导致较少数量的运行时异常或与类型相关的错误,因为大多数类型检查都是在编译时完成的。
  • “动态”类型语言的优势在于:
    • 他们可以帮助进行极快的原型设计,因为开发人员无需了解类型系统,因此dev可以松散地创建变量并运行它,这样可以实现非常快速的原型设计。
  • 静态和动态类型语言列表
    • 静:
      • 爪哇
      • C(C是静态类型语言,但与Java相比,“强”类型较小,因为它允许更多隐式转换)
      • C ++
      • C#
    • 动态:
      • PERL
      • PHP
      • 的Python
      • 的JavaScript
      • 红宝石
  • 类型检查是一项重要的安全功能。假设没有类型检查,并且方法接受“BankAccount”类型的对象,该对象的方法称为“creditAccount(BankAccountDetails)”,现在在运行时,如果没有类型检查,那么我可以传递我自己的类的对象,该对象具有相同的方法“creditAccount(BankAccountDetails)”并且它将被执行,考虑到我们正在谈论面向对象语言,因为OOP支持“多态”和在这里我们讨论的只是“多态”。因此,基本上面向对象的语言(基本上意味着它支持“多态”)没有强大的类型检查可能导致安全问题。

强v / s弱类型语言

  • 强类型语言是指如果精度损失则不允许隐式转换的语言。例如,在Java中,您可以强制转换为“int to long”,因为没有精度损失,但您不能“隐式”转换“long to int”,因为会丢失精度。相反,在弱类型语言中,即使精度不足,也允许隐式转换。
  • 我认为动态类型语言也可以是强类型语言,如果“在运行时”它不允许隐式转换,其中存在精度损失。

更好的进一步阅读

答案 8 :(得分:1)

静态类型语言通常要求您声明变量类型,然后在编译时检查以减少错误。 “静态类型”中的“静态”一词是指“静态代码分析”,它是在执行代码之前检查代码的过程。尽管静态类型语言可以从表达式或实际参数的右侧推断变量的类型,但实际上大多数静态类型语言都需要显式声明变量类型。

动态类型语言通常不要求变量声明具有类型,并且它们根据计算每个赋值语句的右侧或函数调用的实际参数而计算的类型来推断变量类型。由于变量在其生命周期内可以被赋予多个赋值,因此它的类型可以随时间改变,这就是它被称为“动态类型”的原因。此外,运行时环境需要跟踪每个变量的当前类型,因此类型绑定到值而不是变量声明。这可以被认为是运行时类型信息(RTTI)系统。

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

强与弱打字是指语言试图防止由于使用变量而导致的错误的连续性,就好像它是一种类型,而实际上是另一种类型。例如,C和Java都是静态类型语言,但是Java使用比C更强大的类型检查。以下C代码很乐意编译和运行,并且会在运行时将随机值放入变量b,很可能导致错误:

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

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

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

答案 9 :(得分:1)

摘自Addison Wesley的带有应用程序的面向对象的分析和设计,第3页,第66页:

强类型和弱类型以及静态和动态类型的概念 完全不同。强弱打字是指类型 一致性,而静态和动态类型是指 名称绑定到类型。静态类型化(也称为静态绑定) 或早期绑定)表示所有变量的类型以及 表达式在编译时是固定的;动态类型输入 称为后期绑定)表示所有变量的类型和 直到运行时才知道表达式。一种语言可能是两种 强类型和静态类型(Ada),强类型但支持的 动态类型(C ++,Java),或者未类型化但支持的动态类型 键入(Smalltalk)。

答案 10 :(得分:-1)

我最近写了一篇文章,解释了这个确切的主题:

https://dev.to/jiangh/type-systems-dynamic-versus-static-strong-versus-weak-b6c