另外,一个暗示另一个吗?
另外,一个暗示另一个吗?
Answers:
强类型语言和静态类型语言有什么区别?
静态类型的语言具有类型系统,该类型系统在实现时由实现(编译器或解释器)检查。类型检查拒绝某些程序,并且通过检查的程序通常带有一些保证。例如,编译器保证不对浮点数使用整数算术指令。
关于“强类型”的含义并没有真正的共识,尽管专业文献中使用最广泛的定义是使用“强类型”语言,但是程序员不可能解决类型系统所施加的限制。 。这个术语几乎总是用来描述静态类型的语言。
静态类型的反义词是“动态类型”,这意味着
例如,Lua是一种动态类型的语言,除其他外,还具有字符串类型,数字类型和布尔类型。在Lua中,每个值都完全属于一个类型,但是这并不适用于所有动态类型语言的要求。在Lua中,允许串联两个字符串,但不允许串联一个字符串和一个布尔值。
“强类型”的反义词是“弱类型”,这意味着您可以在类型系统周围工作。众所周知,C是弱类型的,因为任何指针类型都可以通过强制转换直接转换为任何其他指针类型。Pascal原本是强类型的,但是设计的监督(未标记的变体记录)在类型系统中引入了漏洞,因此从技术上讲,它是弱类型的。真正强类型语言的示例包括CLU,Standard ML和Haskell。实际上,标准ML已进行了多次修订,以消除在广泛部署该语言后发现的类型系统中的漏洞。
总的来说,谈论“强”和“弱”并没有多大用处。类型系统是否存在漏洞与漏洞的确切数量和性质,在实践中出现的可能性以及利用漏洞的后果相比,并不那么重要。实际上,最好完全避免使用术语“强”和“弱”,因为
业余爱好者经常将它们与“静态”和“动态”混为一谈。
显然,有些人使用“弱类型”来谈论隐性转换的相对盛行或不存在。
专业人士无法就术语的确切含义达成共识。
总体而言,您不太可能通知或启发您的听众。
可悲的事实是,在类型系统方面,“强”和“弱”在技术含义上并没有达成共识。 如果要讨论类型系统的相对强度,最好确切讨论提供了什么保证和不提供什么保证。例如,一个很好的问题是:“是否一定要通过调用该类型的构造函数之一来创建给定类型(或类)的每个值?” 在C语言中,答案是否定的。在CLU,F#和Haskell中,是的。对于C ++,我不确定,我想知道。
相比之下,静态类型化意味着在执行程序之前先检查程序,然后在启动程序之前将其拒绝。 动态类型化意味着在执行过程中会检查值的类型,而类型错误的操作可能会导致程序停止运行或在运行时发出错误信号。静态类型化的主要原因是要排除可能具有此类“动态类型错误”的程序。
一个暗示另一个吗?
从学徒的角度来看,不可以,因为“强”一词实际上没有任何意义。但实际上,人们几乎总是做以下两件事之一:
他们(错误地)使用“强”和“弱”来表示“静态”和“动态”,在这种情况下,他们(错误地)正在交替使用“强类型”和“静态类型”。
他们使用“强”和“弱”来比较静态类型系统的属性。很少有人听到有人谈论“强”或“弱”动态类型系统。除了FORTH,它实际上没有任何类型的类型系统,我无法想到可以颠覆类型系统的动态类型语言。根据定义,这些检查会进入执行引擎,并且在执行每个操作之前都会对其进行检查。
无论哪种方式,如果一个人称一种语言为“强类型”,那么这个人很可能在谈论静态类型的语言。
这经常被误解,所以让我澄清一下。
静态类型是类型绑定到变量的地方。在编译时检查类型。
动态类型是类型绑定到值的地方。在运行时检查类型。
因此,以Java为例:
String s = "abcd";
s
将“永远”成为一个String
。在其生命周期中,它可能指向不同的String
s(因为s
在Java中是引用)。它可能有一个null
值,但绝不会引用Integer
或List
。那是静态类型。
在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
那是动态打字。
(编辑警报!)
强类型键入是一个没有广泛认同的含义的短语。大多数使用该术语来表示静态类型以外的内容的程序员都使用它来暗示编译器强制执行某种类型规则。例如,CLU具有强大的类型系统,该类型系统不允许客户端代码创建抽象类型的值,除非使用该类型提供的构造函数。C具有某种程度强的类型系统,但是由于程序始终可以将一种指针类型的值转换为另一种指针类型的值,因此它可以被“颠覆”到一定程度。因此,例如,在C中,您可以采用由返回的值malloc()
并将其快乐地转换为FILE*
,编译器不会尝试阻止您,甚至会警告您您在做任何狡猾的事情。
(最初的回答是关于一个值“在运行时不改变类型”的。系统,这就是所谓的“强更新问题”。)
弱类型意味着编译器不会强制执行键入纪律,或者强制执行很容易被破坏。
该答案的原始内容将弱类型与隐式转换(有时也称为“隐式提升”)结合在一起。例如,在Java中:
String s = "abc" + 123; // "abc123";
这是代码中隐式提升的示例:123在与串联之前被隐式转换为字符串"abc"
。可以说Java编译器将该代码重写为:
String s = "abc" + new Integer(123).toString();
考虑一个经典的PHP“开始于”问题:
if (strpos('abcdef', 'abc') == false) {
// not found
}
这里的错误是strpos()
返回匹配的索引,即0。将0强制转换为布尔值false
,因此条件实际上为true。解决方案是使用===
而不是==
避免隐式转换。
此示例说明了隐式转换和动态类型的组合如何使程序员误入歧途。
比较一下Ruby:
val = "abc" + 123
这是一个运行时错误,因为在Ruby中,对象 123 并不仅仅因为它恰好传递给了+
方法而隐式转换。在Ruby中,程序员必须明确转换:
val = "abc" + 123.to_s
比较PHP和Ruby是一个很好的例子。两种都是动态类型的语言,但是PHP具有很多隐式转换,而Ruby(如果您不熟悉它,也许会令人惊讶)没有。
这里的重点是静态/动态轴独立于强/弱轴。人们可能会混淆它们,部分原因是强类型和弱类型的定义不仅不那么明确,而且强者和弱者的确切含义也没有真正的共识。因此,强/弱键入更多地是灰色而不是黑色或白色。
因此,回答您的问题:另一种最正确的说法是,静态类型是编译时类型安全,而强类型是运行时类型安全。
原因是静态类型语言的变量具有必须声明的类型,并且可以在编译时进行检查。强类型语言具有在运行时具有类型的值,并且程序员很难在没有动态检查的情况下破坏类型系统。
但重要的是要了解一种语言可以是静态/强,静态/弱,动态/强或动态/弱。
"abc" + 123
是运行时错误,不是ruby中的编译错误。如果这是一个编译错误,那么ruby将被静态键入。
两者都是在两个不同轴上的极点:
强类型表示,a不会自动从一种类型转换为另一种类型。弱类型则相反:Perl可以"123"
在数字上下文中使用字符串,方法是将其自动转换为int 123
。像python这样的强类型语言不会这样做。
静态类型的方法,编译器在编译时便找出每个变量的类型。动态类型语言仅在运行时确定变量的类型。
强类型意味着类型之间的转换之间存在限制。静态类型意味着类型不是动态的-创建变量后就无法更改其类型。
数据强制不一定表示弱类型,因为有时其语法糖:
上面的Java示例由于类型弱而导致
String s = "abc" + 123;
不是弱类型的示例,因为它确实在做:
String s = "abc" + new Integer(123).toString()
如果要构造一个新的对象,数据强制也不是弱类型。Java是弱类型的一个非常糟糕的例子(任何具有良好反射能力的语言很可能不会弱类型)。因为语言的运行时总是知道类型是什么(异常可能是本机类型)。
这与C不同。C是弱类型的最佳示例之一。运行时不知道4个字节是整数,结构,指针还是4个字符。
语言的运行时真正定义了它是否为弱类型,否则是否为真正的公正意见。
编辑: 经过进一步思考,这不一定是正确的,因为运行时不一定必须在运行时系统中将所有类型都进行分类才能成为强类型系统。Haskell和ML具有完整的静态分析,因此可以潜在地忽略运行时的类型信息。
上面已经给出了答案。试图区分强力还是每周和静态还是动态。
强类型:不会自动从一种类型转换为另一种类型
在Go或Python中,像强类型语言一样,“ 2” + 8将引发类型错误,因为它们不允许“类型强制”。
弱(松散)类型的:将自动转换为一种类型: 弱类型的语言(如JavaScript或Perl)不会引发错误,在这种情况下,JavaScript将产生'28',而perl将产生10。
Perl示例:
my $a = "2" + 8;
print $a,"\n";
将其保存到main.pl并运行perl main.pl
,您将获得输出10。
在编程中,程序员针对检查变量类型的点定义静态类型和动态类型。静态类型语言是在编译时进行类型检查的语言,而动态类型语言是在运行时进行类型检查的语言。
这是什么意思
在Go中,它会在运行时之前键入检查(静态检查)。这意味着它不仅会转换和检查执行代码,还会扫描所有代码,甚至在代码运行之前都会引发类型错误。例如,
package main
import "fmt"
func foo(a int) {
if (a > 0) {
fmt.Println("I am feeling lucky (maybe).")
} else {
fmt.Println("2" + 8)
}
}
func main() {
foo(2)
}
将此文件保存在main.go中并运行它,您将为此收到编译失败消息。
go run main.go
# command-line-arguments
./main.go:9:25: cannot convert "2" (type untyped string) to type int
./main.go:9:25: invalid operation: "2" + 8 (mismatched types string and int)
但是这种情况不适用于Python。例如,以下代码块将在第一次foo(2)调用时执行,而在第二次foo(0)调用时失败。这是因为Python是动态类型的,它只翻译和执行其执行的代码并对其进行类型检查。else块永远不会为foo(2)执行,因此甚至不会查看“ 2” + 8,对于foo(0)调用,它将尝试执行该块并失败。
def foo(a):
if a > 0:
print 'I am feeling lucky.'
else:
print "2" + 8
foo(2)
foo(0)
您将看到以下输出
python main.py
I am feeling lucky.
Traceback (most recent call last):
File "pyth.py", line 7, in <module>
foo(0)
File "pyth.py", line 5, in foo
print "2" + 8
TypeError: cannot concatenate 'str' and 'int' objects