2007-12-29
类型系统的四种维度
原文在这里: http://programming.reddit.com/info/63tnv/comments/c02qx55
Latent typing是一种你不需要在源码中的明确的声明你的变量的类型的类型系统.而与之相反的是manifest typing,它需要你在源码中明确的声明你的变量的类型。
Static typing类型系统指的是你的源码中的任何独立的表达式都必须有类型,不管它的类型是直接写在源码中,或者是通过编译器来推断.Dynamic typing是运行时的值才有类型的一种类型系统,因此在它里面程序的表达式能够有任意的类型.
overlap 是一种类型推断系统,像haskell和ocaml用的就是overlap,他们是 statically而且还是latently,他们的编译器能够推断出你的变量的类型。 理论上,这里还有另外一种overlap,它是把变量的类型写在源代码中,可是会直到运行时才会检测类型的是否正确. python3000已经被提议使用这种系统,Common Lisp 和Dylan 使用的就是这种系统.
structural subtyping意味着对象或者表达式能够基于他们的结构(比如他们的方法,变量等等)来进行比较他们的类型的兼容性.相比较而言,nominal subtyping意味着对象基于通过程序员来做的显示的子类声明来进行比较他们的类型的兼容性(比如java的接口).Haskell, ML, 和大部分的动态类型的语言是 structurally-subtyped.工业语言大多数都是nominal subtyping的.
这里还有一个strong vs. weak 类型,他们的区别是是否在运行时动态的转换变量的值 (也就是说要不要到不同的类型)的类型.
下面是类型系统的4种不同的维度:
下面是一些语言所属的类型系统:
Latent typing是一种你不需要在源码中的明确的声明你的变量的类型的类型系统.而与之相反的是manifest typing,它需要你在源码中明确的声明你的变量的类型。
Static typing类型系统指的是你的源码中的任何独立的表达式都必须有类型,不管它的类型是直接写在源码中,或者是通过编译器来推断.Dynamic typing是运行时的值才有类型的一种类型系统,因此在它里面程序的表达式能够有任意的类型.
overlap 是一种类型推断系统,像haskell和ocaml用的就是overlap,他们是 statically而且还是latently,他们的编译器能够推断出你的变量的类型。 理论上,这里还有另外一种overlap,它是把变量的类型写在源代码中,可是会直到运行时才会检测类型的是否正确. python3000已经被提议使用这种系统,Common Lisp 和Dylan 使用的就是这种系统.
structural subtyping意味着对象或者表达式能够基于他们的结构(比如他们的方法,变量等等)来进行比较他们的类型的兼容性.相比较而言,nominal subtyping意味着对象基于通过程序员来做的显示的子类声明来进行比较他们的类型的兼容性(比如java的接口).Haskell, ML, 和大部分的动态类型的语言是 structurally-subtyped.工业语言大多数都是nominal subtyping的.
这里还有一个strong vs. weak 类型,他们的区别是是否在运行时动态的转换变量的值 (也就是说要不要到不同的类型)的类型.
下面是类型系统的4种不同的维度:
引用
1Static (表达式有类型) vs. dynamic (值有类型)
2Strong (没有一个显示的强制转换,这个值的类型就不能被转换为另外的类型) vs. weak (运行时会转换值类型到合适的类型)
3Latent (没有类型声明) vs. manifest (有类型声明)
4Nominal (子类型需要被显式的声明) vs. structural (子类型是由操作可利用的的类型来进行推断的)
2Strong (没有一个显示的强制转换,这个值的类型就不能被转换为另外的类型) vs. weak (运行时会转换值类型到合适的类型)
3Latent (没有类型声明) vs. manifest (有类型声明)
4Nominal (子类型需要被显式的声明) vs. structural (子类型是由操作可利用的的类型来进行推断的)
下面是一些语言所属的类型系统:
引用
Ocaml: static, strong, latent, structural typing
Haskell: static, strong, latent, structural typing, with nominal typing available via newtype and manifest typing through optional type declarations.
Erlang: dynamic, strong, latent, structural typing
Scheme: dynamic, strong, latent, structural typing, with nominal typing available in many object systems.
Common Lisp: dynamic, strong, latent or manifest typing. Same note about structural vs. nominal typing as Scheme, but nominal subtyping is used more often in practice.
Python & Ruby: dynamic, strong, latent, structural typing. Nominal subtyping is available via isinstance or Ruby equivalent, but good practice frowns upon it. PHP: dynamic, weak, latent, nominal or structural typing. Culture is much friendlier to nominal subtyping than Python or Ruby, but it's not required.
Java & C++: mostly static, strong, manifest, nominal typing. The casts give you a form of weak-typing when necessary, and C++ templates are structurally typed.
C: static, generally weak, manifest, nominal typing.
Assembly: dynamic, weak, latent, structural typing
Haskell: static, strong, latent, structural typing, with nominal typing available via newtype and manifest typing through optional type declarations.
Erlang: dynamic, strong, latent, structural typing
Scheme: dynamic, strong, latent, structural typing, with nominal typing available in many object systems.
Common Lisp: dynamic, strong, latent or manifest typing. Same note about structural vs. nominal typing as Scheme, but nominal subtyping is used more often in practice.
Python & Ruby: dynamic, strong, latent, structural typing. Nominal subtyping is available via isinstance or Ruby equivalent, but good practice frowns upon it. PHP: dynamic, weak, latent, nominal or structural typing. Culture is much friendlier to nominal subtyping than Python or Ruby, but it's not required.
Java & C++: mostly static, strong, manifest, nominal typing. The casts give you a form of weak-typing when necessary, and C++ templates are structurally typed.
C: static, generally weak, manifest, nominal typing.
Assembly: dynamic, weak, latent, structural typing
评论
很明显,structural subtyping能够解决目前困扰大多数人的OO建模时的分类问题。
可以这么看:structural是基于行为的建模,而之前的Nominal是基于名词的建模。
基于名词更加依赖人的主观判定,虽然这个判定也是基于对模型行为的分析,只不过是在建模的早期就要决定下来(随后写死到程序里面),而往往早期的决定都是不准确的,加上需求的不断深入,这就导致了后续的对模型结构上的改动,这对程序的影响是巨大的。究其原因就是把人的不成熟的主观判定放到了程序里面。
而如果是直接基于行为的类型系统就不会有这个问题了,人的主观判定还是会不断改变,但是不会体现在程序里面(可能更多地体现在文档里),程序里面都是真确的行为,语言环境本身根据行为进行判定。。。一个清净的世界形成了!!!
在我看来,java中的interface也是为了在nominal的类型系统中解决这个问题的,只不过由于本身的限制,没有structural来的彻底。。。
所以现在的动态类型脚本语言(往往是structural)比较受人欢迎,
但是这类语言本身也有问题,它更依赖代码人员的水平和编写单元测试(没有编译期的语法检查),如果做得不好,更容易出现大量低级bug(可怕的是如果测试人员不能100%覆盖,就无法发现)。。。两难阿。
可以这么看:structural是基于行为的建模,而之前的Nominal是基于名词的建模。
基于名词更加依赖人的主观判定,虽然这个判定也是基于对模型行为的分析,只不过是在建模的早期就要决定下来(随后写死到程序里面),而往往早期的决定都是不准确的,加上需求的不断深入,这就导致了后续的对模型结构上的改动,这对程序的影响是巨大的。究其原因就是把人的不成熟的主观判定放到了程序里面。
而如果是直接基于行为的类型系统就不会有这个问题了,人的主观判定还是会不断改变,但是不会体现在程序里面(可能更多地体现在文档里),程序里面都是真确的行为,语言环境本身根据行为进行判定。。。一个清净的世界形成了!!!
在我看来,java中的interface也是为了在nominal的类型系统中解决这个问题的,只不过由于本身的限制,没有structural来的彻底。。。
所以现在的动态类型脚本语言(往往是structural)比较受人欢迎,
但是这类语言本身也有问题,它更依赖代码人员的水平和编写单元测试(没有编译期的语法检查),如果做得不好,更容易出现大量低级bug(可怕的是如果测试人员不能100%覆盖,就无法发现)。。。两难阿。







评论排行榜