名词系列--语言的类型模型浅析
我们常听到这一类名词:强类型/弱类型,静态类型/动态类型,其实它们都属于语言的类型模型这个范畴。通常来说,这些术语没有一个明确固定的结论,下面以我自身的理解一一介绍下:
强类型和弱类型
通常我们所说的强类型/弱类型,指强类型定义语言和弱类型定义语言
1 强类型定义语言:强制数据类型定义的语言。也就是说,一个变量被赋值后,这个变量的类型就固定了,不能转换成另一个类型(通常只允许以不丢失信息为前提的自动类型转换)。如Java/Python/Ruby
举例:如果你定义了一个整型变量a,那么程序根本不可能将a当作字符串类型处理。强类型定义语言是类型安全的语言。
2 弱类型定义语言:数据类型可以被忽略的语言。它与强类型定义语言相反,一个变量可以赋不同数据类型的值。如js/vbs
举例:js中’’ [] 会被隐式转换成 0 0,结果是 0;js中字符串’123’和整数456是可以比较大小的
注意: 有一类流传的错误的说法是: “强类型语言是指需要进行变量/对象类型声明的语言,一般情况下需要编译执行”/“弱类型语言是指不需要进行变量/对象类型声明的语言,一般情况下不需要编译”
其实,是否需要对变量进行类型声明跟语言的强弱类型无关。上面的错误说法实际上指向了另一个概念:变量是显示声明还是隐式暗示,注意不要混淆。
这里也举个例子: c/Java中,要求对变量进行显示的声明,编写者必须以指定类型明确地关系到每一个变量上。也有些语言如Scala/Haskell支持类型推断,通过编译器帮你猜测变量的类型,从而省略了你在代码中写类型的麻烦。(不知”类型推断”这个特性算不算语法糖) 而python/ruby这类动态语言,往往使用隐式暗示的方式,给变量赋值3.14这个变量就是浮点类型,给变量赋值[1,2,3]就是数组类型。 个人觉得这个概念不必细究,大致了解即可。
小结:
强类型语言,由于类型检查的区别,变量会在编译期确定,或运行中动态确定。但是一旦确定便不可更改,除非使用强制转换。
即使在强类型语言中,也有所谓的“隐式类型转换”(自动类型转换)机制让用户在书写语法上自由一些。比如在Java中,将整数123赋值给一个double变量,并不会导致语法错误,而是会引发隐式类型转换。但即使是隐式类型转换,也如定义中括号内部分所述,通常只允许以不丢失信息为前提的自动类型转换。Java中的转换规则是,存储范围小的类型到存储范围大的类型byte→short(char)→int→long→float→double,本质上,只是将赋的值的类型在规则允许前提下向变量所具有/所定义的类型靠拢,而不会改变变量的类型。“隐式类型转换”这个操作由JVM在编译期自动完成。
动态语言和静态语言
通常我们所说的动态语言、静态语言是指动态类型语言和静态类型语言。
1 动态类型语言:动态类型语言是指在运行期间才去做数据类型检查的语言。动态类型语言在编码期间,永远也不用给任何变量指定数据类型,该语言会在你第一次赋值给变量时,在内部将数据类型记录下来。Python/Ruby就是一种典型的动态类型语言。
2 静态类型语言:与动态类型语言相反,它的数据类型是在编译期确定的。大多数静态类型语言要求编码时显示声明所有变量的数据类型,如前文所述的一些高级语言可以不在编码期声明,编译器会进行类型推断。Java/C++是静态类型语言的典型代表。
对于动态语言与静态语言的区分,套用一句流行的话就是:Static typing where possible, dynamic typing when needed。
总结:
综上可知,python/ruby是强类型的动态语言, Java/C++是强类型的静态语言,JS是弱类型的动态语言
“静态语言/动态语言”与“强/弱类型”之间是没有必然联系的
强类型语言的类型系统在设计上存在更强的约束,这降低了编程的灵活性。但是强类型定义语言带来的严谨性能够有效的避免许多错误。
静态类型语言因为在编译期进行类型检查,可以较早发现错误,而且还可增进运行时期的性能。
静态语言多为编译型语言,而动态语言都是解释型语言,不管它们是不是面向对象。
一句话总结:弱/强类型指的是语言类型系统的类型检查的严格程度。后两者指的是变量与类型的绑定方式。 其实这些概念都是语言的类型系统在设计上的取舍。就类型来说,静态语言因为编译期的存在,在编译期间(甚至智能IDE在编码期)通过语义分析可以处理类型检查,捕获一系列错误,加快运行期的速度。而动态语言类型检查的开销往往会落在运行期,因为动态语言的灵活性(python/ruby可以在运行时把类改的面目全非,甚至绕过类型检查,静态语言惯用的语义分析在动态语言中基本无从发挥)。