静态/动态与强/弱

Dan*_*ell 303 terminology static-typing weak-typing strong-typing dynamic-typing

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

Dar*_*rio 397

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

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

有关更多详细信息,请参阅wiki页面.

  • 令人遗憾的是,许多人并不知道静态/动态不是强/弱......它会真正节省一些偏见和讨论. (31认同)
  • 存在不同程度的"类型弱点".强类型语言可以尝试从字符串到数字的转换.另一方面,HyperTalk(我几十年前使用的一种语言)的类型很弱,"12"+"34"`等于"46",但"12"+"34Q"`等于` 1234Q"`[幸运的是,如果想要连接,可以写"12"和"34".奇怪的是,持有数字的变量将它们存储为双精度浮点数,并且对这些变量的数学运算使用了没有字符串重组的浮点值,但是没有办法询问变量是字符串还是数字. (9认同)
  • @kittylyst我看不出这个答案表明strong是静态的同义词 (9认同)
  • 维基百科有所有的答案.为什么我没有偶然发现这个我不知道的事情. (7认同)
  • ++(大致)单行定义. (2认同)

Nor*_*sey 205

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

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

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

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

  • (+1)为您的建议避免使用"强"和"弱"这两个词. (28认同)

meh*_*met 66

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

例如在Java中:

String str = "Hello";  //statically typed as string
str = 5;               //would throw an error since java is statically typed
Run Code Online (Sandbox Code Playgroud)

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

例如在Python中:

str = "Hello" # it is a string
str = 5       # now it is an integer; perfectly OK
Run Code Online (Sandbox Code Playgroud)

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

例如在Python中:

str = 5 + "hello" 
# would throw an error since it does not want to cast one type to the other implicitly. 
Run Code Online (Sandbox Code Playgroud)

而在PHP中:

$str = 5 + "hello"; // equals 5 because "hello" is implicitly casted to 0 
// PHP is weakly typed, thus is a very forgiving language.
Run Code Online (Sandbox Code Playgroud)

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

  • 这就是PHP需要非常谨慎使用的原因. (3认同)
  • 很好的答案,以及使用具体例子的荣誉. (2认同)

Dav*_*rby 19

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

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

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

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

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

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

  • @mehmet:在C语言中,字符值位于整数域中,因此特定示例不会违反类型安全性。'c'只是99的语法糖。C没有专用的字符类型。 (2认同)

gon*_*onz 14

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

强劲而弱的打字:

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

静态和动态类型

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

静态类型系统是一种机制,通过该机制,编译器检查源代码并将标签(称为"类型")分配给语法片段,然后使用它们来推断有关程序行为的信息.动态类型系统是一种机制,通过该机制,编译器生成代码以跟踪程序使用的数据类型(巧合地,也称为"类型").当然,在这两个系统中使用相同的"类型"一词并非完全巧合; 然而,最好将其理解为具有某种微弱的历史意义.试图找到一个世界观,其中"类型"在两个系统中真正意味着相同的东西,会产生很大的混乱.它没有.

显式/隐式类型:

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


hag*_*wal 8

静态与动态类型语言

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

强v/s弱类型语言

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

很好的进一步阅读


Eva*_*ica 7

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

类型检查是确保程序遵守语言类型兼容性规则的过程.违反规则被称为类型冲突.如果语言以语言实现可以强制执行的方式禁止将任何操作应用于任何不打算支持该操作的对象,则称该语言是强类型的.如果一种语言是强类型的,并且可以在编译时执行类型检查,则称该语言是静态类型的.从严格意义上说,很少有语言是静态类型的.在实践中,该术语通常应用于可以在编译时执行大多数类型检查的语言,其余的可以在运行时执行.

一些例子:Ada是强类型的,并且大部分是静态类型的(必须在运行时检查某些类型约束).Pascal实现也可以在编译时进行大部分类型检查,尽管语言的类型不是很强:未标记的变体记录(将在7.3.4节中讨论)是它唯一的漏洞.C89的键入方式明显比其前身方言更强,但仍然比Pascal的输入强度更低.它的漏洞包括联合,具有可变参数数量的子程序,以及指针和数组的互操作性(将在第7.7.1节中讨论).C的实现很少在运行时检查任何内容.

动态(运行时)类型检查是一种后期绑定的形式,并且往往会在延迟其他问题的语言中找到,直到运行时.Lisp和Smalltalk是动态(虽然强烈)类型.大多数脚本语言也是动态类型的; 一些(例如,Python和Ruby)是强类型的.具有动态作用域的语言通常是动态类型化的(或者根本不打字):如果编译器无法识别名称所引用的对象,则通常也无法确定对象的类型.

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

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

静态/动态 - 强/弱打字平面


Nic*_*ico 5

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

这里有两个例子:

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

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

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


deb*_*yan 5

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

\n

在每种编程语言中,为了最大限度地减少出错的机会,都会在程序执行之前或期间进行类型检查。根据类型检查的时机,编程语言分为两种类型:静态类型动态类型语言。

\n

另外,根据是否发生隐式类型转换,编程语言分为两种类型:强类型弱类型语言。

\n

打字-静态与动态,强与弱

\n

静态类型:

\n
    \n
  • 类型检查在编译时完成

    \n
  • \n
  • 在源代码中,在声明变量时,必须显式指定该变量的数据类型。因为如果在源代码中指定了数据类型,那么在编译时源代码将转换为机器代码并且可以进行类型检查

    \n
  • \n
  • 这里的数据类型与变量相关联,例如,int count。并且这种关联是静态的或固定的

    \n
  • \n
  • 如果我们尝试int count通过将其他数据类型 ( ) 的值分配给已声明的变量 ( int count = "Hello") 来更改其数据类型,那么我们将收到错误

    \n
  • \n
  • 如果我们尝试通过重新声明已声明的变量来更改数据类型(int count使用其他数据类型(boolean count ) 来更改数据类型,那么我们也会收到错误

    \n
  • \n
\n
int count;         /* count is int type, association between data type\n                      and variable is static or fixed */\n\ncount = 10;        // no error \ncount = \'Hello\';   // error \nboolean count;     // error \n
Run Code Online (Sandbox Code Playgroud)\n
    \n
  • 由于类型检查和类型错误检测是在编译时完成的,这就是为什么在运行时不需要进一步的类型检查。因此程序变得更加优化,执行速度更快

    \n
  • \n
  • 如果我们想要更严格的代码,那么选择这种类型的语言是更好的选择

    \n
  • \n
  • 示例:Java、C、C++、Go、Swift 等。

    \n
  • \n
\n

动态类型:

\n
    \n
  • 类型检查在运行时完成

    \n
  • \n
  • 在源代码中,在声明变量时,无需显式指定该变量的数据类型。因为在运行时的类型检查期间,语言系统根据分配给该变量的值的数据类型来确定变量类型

    \n
  • \n
  • 这里的数据类型与分配给变量的值相关联,例如,var foo = 10,10 是一个数字,所以现在 foo 是数字数据类型。但这种关联是动态的或灵活的

    \n
  • \n
  • 我们可以var foo = 10通过分配其他数据类型的值(foo = "Hi"它,不会出现错误

    \n
  • \n
  • 我们可以轻松地更改已声明变量 ( ) 的数据类型var foo = 10,方法是使用其他数据类型的值重新声明它 (var foo = true,不会出现错误

    \n
  • \n
\n
var foo;            // without assigned value, variable holds undefined data type \n\nvar foo = 10;       // foo is Number type now, association between data \n                    // type and value is dynamic / flexible \nfoo = \'Hi\';         // foo is String type now, no error \nvar foo = true;     // foo is Boolean type now, no error \n
Run Code Online (Sandbox Code Playgroud)\n
    \n
  • 由于类型检查和类型错误检测是在运行时完成的,这就是为什么程序变得不太优化,导致执行速度变慢的原因。尽管这些类型的语言如果实现 JIT 编译器,执行速度会更快

    \n
  • \n
  • 如果我们想轻松编写和执行代码,那么这种类型的语言是更好的选择,但在这里我们可能会遇到运行时错误

    \n
  • \n
  • 示例:Python、JavaScript、PHP、Ruby 等。

    \n
  • \n
\n

强类型:

\n
    \n
  • 严格维护数据类型相关的规则和限制

    \n
  • \n
  • 从一种数据类型到另一种数据类型的转换必须显式完成,不能隐式类型转换

    \n
  • \n
\n
# in python, "5" cannot automatically get converted to 5\npybar = "5"\n\nprint(10 + pybar) \xc2\xa0 \xc2\xa0 # error, no `+` operation between `int` and `str` \n
Run Code Online (Sandbox Code Playgroud)\n
    \n
  • 类型检查可以在编译时或运行时完成。这意味着强类型语言可以是静态类型的,也可以是动态类型的

    \n
  • \n
  • 示例:Python、Java、Ruby、C# 等。

    \n
  • \n
\n

弱类型:

\n
    \n
  • 数据类型相关的规则和限制维护松散

    \n
  • \n
  • 从一种数据类型到另一种数据类型的转换可以隐式发生

    \n
  • \n
  • 如果我们在两个不匹配的数据类型的值之间执行某些操作,那么这种类型的语言可能不会抛出错误。相反,弱类型语言将应用自己的隐式类型转换规则并返回一些结果

    \n
  • \n
\n
jsbar = "5";\n\nalert(10 + jsbar);  /* "105", no error as javascript implicitly coerces Number 10 \nto String "10", so that it can be concatenated with other operand jsbar i.e. "5" */\n
Run Code Online (Sandbox Code Playgroud)\n
    \n
  • 类型检查可以在编译时或运行时完成。这意味着弱类型语言可以是静态类型的,也可以是动态类型的

    \n
  • \n
  • 示例:JavaScript、C、C++、PHP 等。

    \n
  • \n
\n