强types语言和静态types语言有什么区别?
另外,一个暗示另一个?
强types语言和静态types语言有什么区别?
静态types语言有一个types系统,在编译时由实现(编译器或解释器)检查。 types检查会拒绝一些程序,而通过检查的程序通常会有一些保证; 例如,编译器保证不在浮点数上使用整数算术指令。
虽然在专业文献中使用最广泛的定义是“强types”的语言,程序员不可能去解决types系统所施加的限制。 这个术语几乎总是用来描述静态types的语言。
静态与dynamic
静态types的相反是“dynamictypes”,这意味着
- 在运行时使用的值被分为types。
- 对于如何使用这些值有一些限制。
- 违反这些限制时,将违规报告为(dynamic)types错误。
例如,dynamictypes语言Lua具有stringtypes,数字types和布尔types等等。 在Lua中,每个值都属于一种types,但这不是所有dynamictypes语言的要求。 在Lua中,允许连接两个string,但不允许连接一个string和一个布尔值。
强与弱
与“强types”相反的是“弱types”,这意味着你可以在types系统中工作。 C是非常弱的types,因为任何指针types都可以简单地通过转换转换为任何其他的指针types。 帕斯卡打算是强types的,但devise中的疏忽(无标记的变体logging)在types系统中引入了一个漏洞,所以在技术上它是弱types的。 真正强types的语言包括CLU,Standard ML和Haskell。 标准ML实际上经过了几次修改,以消除语言广泛部署后发现的types系统漏洞。
这里究竟发生了什么?
总的来说,谈论“强”和“弱”是没有用的。 一个types系统是否存在漏洞,其漏洞的确切数量和性质,实践中可能出现的可能性,以及漏洞的后果是什么,都不那么重要。 在实践中, 最好避免使用“强”和“弱”的术语 ,因为
-
业余爱好者经常把它们与“静态”和“dynamic”混为一谈。
-
显然,“弱打字”被一些人用来谈论相对普遍或缺乏隐式转换。
-
专业人士无法就这些术语的含义达成一致。
-
总的来说,你不可能告知或启发你的观众。
可悲的事实是,就types体系而言, “强”和“弱”在技术上没有普遍的一致意义。 如果你想讨论types系统的相对强度,最好是讨论什么保证是什么,不提供。 例如,要问的一个好问题是:“是否通过调用某个types的构造函数来保证创build的types(或类)的每个值都是? 在C中,答案是否定的。 在CLU,F#和Haskell中是肯定的。 对于C ++我不确定 – 我想知道。
相比之下, 静态types意味着程序在被执行之前被检查 ,并且程序在开始之前可能被拒绝。 dynamictypes意味着在执行期间检查值的types,而types错误的操作可能会导致程序在运行时暂停或以其他方式发出错误信号。 静态types的主要原因是排除可能有这种“dynamictypes错误”的程序。
一个人暗示另一个?
在迂腐的层面上,不,因为“强”这个词并不意味着什么。 但在实践中,人们几乎总是做两件事之一:
-
它们(错误地)使用“强”和“弱”来表示“静态”和“dynamic”,在这种情况下,它们(错误地)使用“强types”和“静态types”。
-
他们用“强”和“弱”来比较静态types系统的性质。 听到有人谈论“强”或“弱”的dynamictypes系统是非常罕见的。 除了没有任何types系统的FORTH之外,我想不出一种dynamictypes的语言,在这种语言中,types系统可以被颠覆。 按照定义进行sorting,这些检查会被放入执行引擎中,并在执行之前检查每个操作的完整性。
无论哪种方式,如果一个人称某种语言为“强types”,那么这个人很可能会谈论一种静态types的语言。
这经常被人误解,所以让我来澄清一下。
静态/dynamicinput
静态types是types绑定到variables的地方 。 types在编译时被检查。
dynamictypes是types绑定到值的地方 。 types在运行时被检查。
所以以Java为例:
String s = "abcd";
将永远是一个String
。 在它的生命期间可能会指向不同的String
(因为s
是Java中的引用)。 它可能有一个null
值,但不会引用Integer
或List
。 这是静态types。
在PHP中:
$s = "abcd"; // $s is a string $s = 123; // $s is now an integer $s = array(1, 2, 3); // $s is now an array $s = new DOMDocument; // $s is an instance of the DOMDocument class
这是dynamic打字。
强/弱打字
(编辑警报!)
强打字是一个没有广泛同意的短语。 大多数使用这个术语来表示静态types以外的东西的程序员使用它来暗示编译器强制执行types规范。 例如,CLU有一个强types系统,不允许客户端代码创build一个抽象types的值,除非使用该types提供的构造函数。 C有一个强大的types系统,但它可以被“颠覆”到某种程度,因为程序总是可以将一个指针types的值转换为另一个指针types的值。 例如,在C语言中,你可以获得malloc()
返回的值,并将其高兴地转换为FILE*
,而编译器不会试图阻止你,或者甚至警告你,你做的任何事情都是狡猾的。
(原来的回答是关于“在运行时不改变types”的价值的一些东西我已经了解了许多语言devise者和编译器的作者,并且还不知道在运行时谈到了更改types的值,除了可能有一些非常先进的types的研究系统,这被称为“强更新问题”)。
弱打字意味着编译器不强制打字,或者强制执行很容易被破坏。
这个答案的原文将弱types与隐式转换 (有时也称为“隐式升迁”)混为一谈。 例如,在Java中:
String s = "abc" + 123; // "abc123";
这是代码是隐式升级的示例:123在与"abc"
连接之前被隐式转换为string。 可以认为Java编译器将该代码重写为:
String s = "abc" + new Integer(123).toString();
考虑一个经典的PHP“开始”的问题:
if (strpos('abcdef', 'abc') == false) { // not found }
这里的错误是strpos()
返回匹配的索引,即0被强制为boolean false
,因此条件实际上是真的。 解决方法是使用===
而不是==
来避免隐式转换。
这个例子说明了隐式转换和dynamictypes的组合如何导致程序员误入歧途。
与Ruby比较:
val = "abc" + 123
这是一个运行时错误,因为在Ruby中, 对象 123 并不是仅仅因为它传递给+
方法而被隐式转换。 在Ruby中,程序员必须明确地进行转换:
val = "abc" + 123.to_s
比较PHP和Ruby是一个很好的例子。 两者都是dynamictypes的语言,但PHP有很多隐式转换,而Ruby(也许令人惊讶的是,如果你不熟悉它)不会。
静态/dynamic与强/弱
这里的要点是,静态/dynamic轴独立于强/弱轴。 人们可能会混淆它们,部分原因是,强types与弱types不仅没有明确的界定,对强弱意味着什么也没有真正的共识。 出于这个原因,强/弱打字更多的是灰色而不是黑色或白色。
所以要回答你的问题:另一种看待这个问题的方法大部分是正确的,就是说静态types是编译时types安全的,强types是运行时types安全的。
原因是静态types语言中的variables有一个必须声明的types,并且可以在编译时检查。 强types语言在运行时具有types的值,程序员很难在没有dynamic检查的情况下颠覆types系统。
但重要的是要明白,一种语言可以是静态/强大,静态/弱,dynamic/强或dynamic/弱。
强types意味着types之间的转换有限制。 静态types意味着types不是dynamic的 – 一旦创build了variables,就不能改变其types。
数据强制不一定意味着弱types,因为有时它的合成糖:
Java上面的例子因为是弱types的
String s = "abc" + 123;
不是微弱的例子,因为它真的在做:
String s = "abc" + new Integer(123).toString()
如果你正在构build一个新的对象,数据强制也不是弱types的。 Java是弱types的一个非常糟糕的例子(任何具有良好reflection的语言很可能不会被弱types化)。 因为语言的运行时总是知道types是什么(exception可能是本地types)。
这不像C. C是弱types的最好的例子之一。 运行时不知道如果4个字节是一个整数,一个结构,一个指针或一个4个字符。
语言的运行时间确实定义了它是否弱types,否则它真的只是意见。
编辑: 经过进一步的思考,这不一定是真实的,因为运行时不必将运行时系统中的所有types都指定为强types系统。 Haskell和ML有这样完整的静态分析,他们可以从运行时潜在的ommittypes信息。
两者都在两个不同的轴上:
- 强types与弱types
- 静态types与dynamictypes
强types意味着,不会自动从一种types转换为另一种types。 弱types是相反的:Perl可以在数字上下文中使用类似"123"
的string,自动将其转换为int 123
。 像Python这样的强types语言不会这样做。
静态types意味着,编译器在编译时计算出每个variables的types。 dynamictypes语言只能在运行时找出variables的types。
强types可能意味着variables具有明确定义的types,并且在expression式中有不同typesvariables的组合规则。 例如,如果A是一个整数,而B是一个浮点数,那么关于A + B的严格规则可能是A被转换为一个浮点数,结果返回为一个浮点数。 如果A是一个整数,B是一个string,严格的规则可能是A + B无效。
静态types的input可能意味着types在编译时(或者对于非编译语言是等价的)被分配,并且在程序执行期间不能被改变。
请注意,这些分类不是相互排斥的,实际上我希望它们经常一起出现。 许多强types语言也是静态types的。
请注意,当我使用“可能”一词时,这是因为这些术语没有普遍接受的定义。 正如你现在已经从答案中看到的那样。
一个并不意味着另一个。 对于静态types的语言,这意味着所有variables的types在编译时是已知的或推断的。
强types语言不允许您使用另一种types。 C是弱types语言,是强types语言不允许的一个很好的例子。 在C中,你可以传递一个错误types的数据元素,它不会抱怨。 在强types语言中,你不能。
在计算机编程中,编程语言通常被称为强types或弱types。 这些术语没有一个精确的定义,但是一般来说,强types语言如果传递给函数的参数与预期的types不一致,则更可能产生错误或拒绝编译。 另一方面,一个非常弱types的语言可能会产生不可预知的结果,或者可能执行隐式types转换