首页 文章

静态/动态与强/弱

提问于
浏览
279

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

10 回答

  • 3
    • 静态/动态键入是关于获取 when 类型信息(在编译时或在运行时)

    • 强/弱键入是关于 how strictly 类型的区分(例如,语言是否尝试从字符串到数字进行隐式转换) .

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

  • 1

    你已经发现业余爱好者用来谈论编程语言的术语情有独钟 . Don't use the terms "strong" and "weak" typing ,因为他们没有普遍认同的技术含义 . 相比之下, static typing 表示程序是 checked before being executed ,程序可能会在启动之前被拒绝 . Dynamic typing 表示 values are checked during execution 的类型和类型不佳的操作可能导致程序暂停或以其他方式 signal an error at run time . 静态类型的主要原因是排除可能具有此类"dynamic type errors"的程序 .

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

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

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

  • 19

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

    例如在Java中:

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

    而在 dynamically typed language 中,类型是动态的,这意味着在将变量设置为类型后,您可以更改它 . 这是因为键入与值而不是变量相关联 .

    例如在Python中:

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

    另一方面,语言中的 strong/weak typing 与隐式类型转换有关(部分取自@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.
    

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

  • 372

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

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

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

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

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

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

  • 61

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

    强劲而弱的打字:

    可能最常见的类型系统被分类为“强”或“弱” . 这是不幸的,因为这些词根本没有任何意义 . 在有限的程度上,可以将两种语言与非常相似的类型系统进行比较,并将其指定为具有这两种系统中较强的一种 . 除此之外,这些词语毫无意义 .

    静态和动态类型

    这几乎是具有实际意义的唯一类型系统的常见分类 . 事实上,它的重要性经常被低估[...]动态和静态类型系统是两个完全不同的东西,其目标恰好发生了部分重叠 . 静态类型系统是一种机制,通过该机制,编译器检查源代码并将标签(称为“类型”)分配给语法片段,然后使用它们来推断有关程序行为的信息 . 动态类型系统是一种机制,通过该机制,编译器生成代码以跟踪程序使用的数据类型(巧合地,也称为“类型”) . 当然,在这两个系统中使用相同的“类型”一词并非完全巧合;然而,最好将其理解为具有某种微弱的历史意义 . 试图找到一个世界观,其中“类型”在两个系统中实际上意味着相同的东西,会产生很大的混乱 . 它没有 .

    显式/隐式类型:

    当使用这些术语时,它们指的是编译器对程序的静态类型部分进行推理的程度 . 所有编程语言都有某种形式的推理类型 . 有些人比其他人更多 . ML和Haskell有隐式类型,因为不需要(或者很少,取决于使用的语言和扩展)类型声明 . Java和Ada具有非常明确的类型,并且不断地声明事物的类型 . 所有上述(相对于C和C,例如)强静态类型系统 .

  • 13

    从斯科特的编程语言语用学,第3版第291页,我们有

    类型检查是确保程序遵守语言类型兼容性规则的过程 . 违反规则被称为类型冲突 . 如果语言以语言实现可以强制执行的方式禁止将任何操作应用于任何不打算支持该操作的对象,则称该语言是强类型的 . 如果一种语言是强类型的,并且可以在编译时执行类型检查,则称该语言是静态类型的 . 从严格意义上说,很少有语言是静态类型的 . 在实践中,该术语通常应用于可以在编译时执行大多数类型检查的语言,其余的可以在运行时执行 . 一些例子:Ada是强类型的,并且大部分是静态类型的(必须在运行时检查某些类型约束) . Pascal实现也可以在编译时进行大多数类型检查,尽管语言的类型不是很强:未标记的变体记录(将在7.3.4节中讨论)是它唯一的漏洞 . C89的键入方式明显比其前身方言更强,但仍然比Pascal的输入强度更低 . 它的漏洞包括联合,具有可变参数数量的子程序,以及指针和数组的互操作性(将在第7.7.1节中讨论) . C的实现很少在运行时检查任何内容 . 动态(运行时)类型检查是一种后期绑定的形式,并且往往会在延迟其他问题的语言中找到,直到运行时 . Lisp和Smalltalk是动态(虽然强烈)类型 . 大多数脚本语言也是动态类型的;一些(例如,Python和Ruby)是强类型的 . 语言动态作用域通常是动态类型化的(或者根本不打字):如果编译器无法识别名称所引用的对象,则通常也无法确定对象的类型 .

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

    我试图将斯科特的描述翻译成一个很好的图表,我在下面发布了这个图表 .

    The Static/Dynamic - Strong/Weak Typing Plane

  • 6

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

    这里有两个例子:

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

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

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

  • 193

    静态v / s动态类型语言

    • 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. 现在,相比之下, 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 ,如果一个类型被关联,那么它可能是JS中的“var”这样的泛型类型,它对字符串和数字都有好处 .

    • “动态类型检查语言的实现通常将每个运行时对象与包含其类型信息的类型标记(即,对类型的引用)相关联 . 此运行时类型信息(RTTI)还可用于实现动态调度,后期绑定,向下转换,反射和类似功能 . “

    • 即使语言是静态类型的,它仍然可以有一些动态类型的功能,这基本上意味着在运行时也会进行某种类型的检查 . 这在类型的转换中很有用 .

    • “无法静态检查许多有用且常用的编程语言功能,例如向下转换 . 因此,许多语言都将进行静态和动态类型检查;静态类型检查器验证它可以做什么,动态检查验证其余部分 . “

    • “某些语言允许编写非类型安全的代码 . 例如,在C语言中,程序员可以在任何两种具有相同大小的类型之间自由地转换值 . “

    • Advantage of “statically” typed languages are that:

    • 由于大多数类型检查都是在编译时完成的,因此解释器或运行时可以全速运行,而不必担心类型 .

    • 它导致较少数量的运行时异常或与类型相关的错误,因为大多数类型检查是在编译时完成的 .

    • Advantage of “dynamically” typed languages are that:

    • 他们可以帮助进行极快的原型设计,因为开发人员不需要理解类型系统,因此dev可以松散地创建变量并运行它,这导致了非常快速的原型设计 .

    • List of statically and dynamically typed languages

    • 静态地:

    • Java

    • C(C是一种静态类型语言,但与Java相比较“强”类型,因为它允许更多的隐式转换)

    • C.

    • C#

    • 动态:

    • PERL

    • PHP

    • Python

    • JavaScript

    • Ruby

    • Type checking is an important security feature. 假设没有类型检查,并且方法接受“BankAccount”类型的对象,该对象有一个名为“creditAccount(BankAccountDetails)”的方法,现在在运行时如果没有类型检查那么我可以传递一个对象我自己的类具有相同的方法“creditAccount(BankAccountDetails)”并且它将被执行,考虑到我们正在谈论面向对象语言,因为OOP支持“多态”,这里我们讨论的只是“多态” . 因此,基本上面向对象的语言(基本上它意味着它支持“多态”)没有强类型检查可能导致安全问题 .

    强烈v / s弱类型语言

    • 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.

    • 我认为动态类型语言也可以是强类型语言,如果“在运行时”它不允许隐式转换,其中精度损失 .


    更好的读数

  • 5

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

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

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

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

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

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

    String a = "123"
    int b = (int)a;
    
  • -1

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

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

相关问题