如何看待Typescript中的重载(Overload)?

您所在的位置:网站首页 ovarload 如何看待Typescript中的重载(Overload)?

如何看待Typescript中的重载(Overload)?

2023-04-14 04:16| 来源: 网络整理| 查看: 265

几点。

第一,常见的静态类型语言中的overload是发生在编译时的,编译器可以清楚的将每一处同名函数调用对应到你写的不同的函数实现。也就是,同名只是一个(让程序员看到的)假象。如你写了fun(x),有两个实现fun(x: string)、fun(x: int),真正编译后的程序里实际会有两个函数,假设记做fun_string和fun_int,而每个fun(x)调用会被自动替换成fun_string(x)或fun_int(x)。有没有可能编译器无法确定替换成哪一个?当然有可能,这个时候编译器就报错了嘛,意思是你代码写错啦!

第二,JavaScript是动态类型,所以是没有上面这种意义上的overload的。但JS程序员可以在运行时判断类型,也就是 function fun(x) { if (typeof x === 'string') ... else/* assume x is int */ ... } 。TypeScript 的『overload』只是允许给这样的函数标注多个类型。某轮说这是『绕过编译器类型检查』,是有问题的。这不是绕过,把函数参数标记为 (x: any) 才叫『绕过』。不过因为函数的具体实现只有一个,代码本身会比上面那种overload要麻烦一些,比如说为了检测类型偶尔你需要自己实现一些 type guard。至于说『下标函数也不能自己写,这个很傻逼』,我估计某轮指的是 operator overload,然而很多语言都不允许(比如 java)。所以单单骂 TS/JS 有点扯。

第三,TS理论上当然是可以实现传统的 overload 的,比如直接生成两个函数,fun1、fun2。问题是从TS与JS的互操作性上来说,这事情就比较麻烦,比如一个js项目用了ts的库,我不能直接写fun,而得写fun1、fun2。本来 overload 就是希望给程序员提供便利,但现在就并没有什么卵用。其实像java之类有『真』重载的语言编译到js,或直接和js互操作,都有类似的问题。早在二十年前rhino里就有这问题——你在js里要指定到底调用的是哪一个java的重载方法是非常烦人的。特别是构造器,一般函数你说编译成fun_string、fun_int也就算了,但构造器呢?相当棘手。

那TS能不能自动生成一个把多个实现合并起来的fun呢?

不好办。因为runtime的类型检查和编译时类型检查是很不一样的(可以上网去查下override和overload的差异,前者通常就是runtime的),而且TS编译后并没有保留类型信息,所以复杂一点的类型根本没法在runtime检查。并且不带有runtime类型检查是TS的设计目标确定的,所谓by design是也。(其他答案也都提到了这一点。)

最后,这种只有『函数签名重载』而函数实现却还是只有一个,看上去只是因为TS要迁就JS而导致的限制。但从另外一方面说,『真』重载本身也并非只有优点没有缺点,如维基词条里写的:

CaveatsIf a method is designed with an excessive number of overloads, it may be difficult for developers to discern which overload is being called simply by reading the code. This is particularly true if some of the overloaded parameters are of types that are inherited types of other possible parameters (for example "object"). An IDE can perform the overload resolution and display (or navigate to) the correct overload.Type based overloading can also hamper code maintenance, where code updates can accidentally change which method overload is chosen by the compiler.

因此不少语言故意不支持重载。【至于运算符重载,争议就更大了。本题不讨论。】

TS的『假』重载却没有上述这些问题。派发规则是在函数里显式写的。也不存在代码更新导致编译器改变方法选择(因为只有一个真正的方法)。

再如,分布式的、跨语言的场合,比如rpc框架,重载也可能是一个麻烦的问题。而像TS这种最终其实只有一个函数实现,就一定程度上规避了这些问题。

以上。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3