重载
2023年06月27日
一、方法重载
1.1 优势
- 结构分明,让代码可读性,可维护性提升许多,而且代码更漂亮
- 各司其职,自动提示方法和属性,每个重载方法完成各自的功能,输出取值时不用强制转换就能出动自动提示,从而提高开发效率。
- 更利于功能扩展
1.2 规则
方法重载 一组具有相同的名字,不同的参数列表、不同的返回值的方法。
方法签名 方法签名 = 方法名称 + 方法参数个数 + 方法参数类型 + 返回值类型 四者合成。在TypeScript中,包含了实现签名和重载签名,实现签名是一种方法签名,重载签名也是一种方法签名。
完整的方法重载定义规则如下:
- 规则1: 由一个实现签名 + 一个或多个重载签名合成
- 规则2: 外部调用方法重载定义的方法时,只能调用重载签名,不能调用实现签名。这是因为实现签名下的方法体是给重载签名编写的,实现签名只是在定义时起到了统领所有重载签名的作用,在执行调用时就看不到实现签名了。
- 规则3: 调用重载方法时,会根据传递的参数来判断你调用的是哪一个方法
- 规则4: 只有一个方法体,只有实现签名配备了方法体,所有的重载签名都只有签名,没有配备方法体。
- 规则5: 关于参数类型规则完整总结如下:
- 无论重载签名由几个参数、参数是何种类型,实现签名都可以是一个无参方法签名
- 实现签名参数个数可以少于重载签名的参数个数,但实现签名如果准备包含重载签名的某个位置的参数,那实现签名就必须兼容所有重载签名该位置的参数类型
- 规则6: 关于重载签名和实现签名的返回值类型规则完整总结如下:
- 必须给重载签名提供返回值类型,TypeScript 无法默认推导
- 提供给重载签名的返回值类型不一定为其执行时的真实返回值类型,可以为重载签名提供真实返回值类型,也可以提供 void 或 unknown 或 any 类型。如果重载签名的返回值类型是 void 或 unknown 或 any 类型,那么将由实现签名来决定重载签名执行时的真实返回值类型。当然为了调用时能有自动提示+可读性更好+避免可能出现了类型强制转换,强烈建议为重载签名提供真实返回值类型。
- 不管重载签名返回值类型时何种类型,实现签名都可以返回 any 类型 或者 unknown 类型,当然一般我们两者都不选择,让 TypeScript 默认为实现签名自动推导返回值类型
1.3 场景
-
实现 JavaScript 版的 ArrayList
class ArrayList {
constructor(public element: Array<object>) {
}
get(index: number) {
return this.element[index];
}
show() {
this.element.forEach((ele) => {
console.log(ele);
});
}
remove(value: number): number
remove(value: object): object
remove(value: number | object): number | object {
this.element = this.element.filter((ele, index) => {
if (typeof value === 'number') {
return index !== value;
} else {
return value !== ele;
}
});
return value;
}
}
const one = {
id: 1,
name: '哈哈'
}
const two = {
id: 2,
name: '嘻嘻'
}
const three = {
id: 3,
name: '呵呵’'
}
const array = [one, two, three]
const newArrayList = new ArrayList(array);
newArrayList.remove(1);
newArrayList.show();
newArrayList.remove(three);
newArrayList.show();
二、构造器重载
2.1 优势
- 结构分明,让代码可读性,可维护性提升许多,而且代码更漂亮
- 各司其职,自动提示方法和属性,每个重载方法完成各自的功能,输出取值时不用强制转换就能出动自动提示,从而提高开发效率。
- 更利于功能扩展
2.2 规则
构造器重载 一组具有相同的名字,不同的参数列表、不同的返回值的构造器。
构造器签名 构造器签名 = 构造器名称 + 构造器参数个数 + 构造器参数类型 + 返回值类型 四者合成。在TypeScript中,包含了实现签名和重载签名,实现签名是一种构造器签名,重载签名也是一种构造器签名。
完整的构造器重载定义规则如下:
- 规则1: 由一个实现签名 + 一个或多个重载签名合成
- 规则2: 外部调用构造器重载定义的构造器时,只能调用重载签名,不能调用实现签名。这是因为实现签名下的构造器体是给重载签名编写的,实现签名只是在定义时起到了统领所有重载签名的作用,在执行调用时就看不到实现签名了。
- 规则3: 调用重载构造器时,会根据传递的参数来判断你调用的是哪一个构造器
- 规则4: 只有一个构造器体,只有实现签名配备了构造器体,所有的重载签名都只有签名,没有配备构造器体。
- 规则5: 关于参数类型规则完整总结如下:
- 无论重载签名由几个参数、参数是何种类型,实现签名都可以是一个无参构造器签名
- 实现签名参数个数可以少于重载签名的参数个数,但实现签名如果准备包含重载签名的某个位置的参数,那实现签名就必须兼容所有重载签名该位置的参数类型
构造器时是方法吗?
对象调用的才是方法,但是TypeScript 构造器是在对象空间地址赋值给对象变量之前被调用,而不是用来被对象变量调用的。构造器 可以说成是构造函数,但不能被看成是一个方法。
构造器有返回值吗?
TypeScript 构造器 会隐式的返回this。
构造器重载的意义
构造器重载 和 函数重载 使用基本相同,主要区别是: TypeScript 类构造器重载签名和实现签名都不需要管理返回值。TypeScript 类 只可以定义一个构造器,如果有用到多个构造器的场景,需要用构造器重载来解决。
2.3 场景
-
多种场景下求面积
type ParamsType = {
width:number;
height:number;
}
class Square{
public width:number;
public height:number;
constructor(width:number,height:number)
constructor(value:ParamsType)
constructor(value:number | ParamsType,height:number = 0){
if(typeof value === 'number'){
this.width = value;
this.height = height;
}else{
this.width = value.width;
this.height = value.height;
}
}
getArea(){
return this.width * this.height;
}
}
const s1 = new Square(30,40);
console.log(s1.getArea());
const s2 = new Square({width:30,height:40});
console.log(s2.getArea());