有人在TypeScript中做过构造函数重载吗?在语言规范(v 0.8)的第64页,有描述构造函数重载的语句,但没有给出任何示例代码。
我现在正在尝试一个非常基本的类声明;它是这样的,
interface IBox {
x : number;
y : number;
height : number;
width : number;
}
class Box {
public x: number;
public y: number;
public height: number;
public width: number;
constructor(obj: IBox) {
this.x = obj.x;
this.y = obj.y;
this.height = obj.height;
this.width = obj.width;
}
constructor() {
this.x = 0;
this.y = 0;
this.width = 0;
this.height = 0;
}
}
当运行tsc BoxSample。Ts,它抛出一个重复的构造函数定义——这是显而易见的。任何帮助都是感激的。
TypeScript允许你声明重载,但是你只能有一个实现,而且这个实现必须有一个与所有重载兼容的签名。在你的例子中,这可以很容易地用一个可选参数来完成,
interface IBox {
x : number;
y : number;
height : number;
width : number;
}
class Box {
public x: number;
public y: number;
public height: number;
public width: number;
constructor(obj?: IBox) {
this.x = obj?.x ?? 0
this.y = obj?.y ?? 0
this.height = obj?.height ?? 0
this.width = obj?.width ?? 0;
}
}
或者使用更通用的构造函数进行两次重载,
interface IBox {
x : number;
y : number;
height : number;
width : number;
}
class Box {
public x: number;
public y: number;
public height: number;
public width: number;
constructor();
constructor(obj: IBox);
constructor(obj?: IBox) {
this.x = obj?.x ?? 0
this.y = obj?.y ?? 0
this.height = obj?.height ?? 0
this.width = obj?.width ?? 0;
}
}
参见游乐场
你应该记住……
contructor()
constructor(a:any, b:any, c:any)
它和new()或者new("a","b","c")一样
Thus
constructor(a?:any, b?:any, c?:any)
和上面一样,而且更灵活…
新()或新的(“a”)或(“a”、“b”)或新(“a”、“b”、“c”)
Box类试图定义多个构造函数实现。
只有最后一个构造函数重载签名被用作类构造函数实现。
在下面的示例中,请注意构造函数实现的定义与前面的任何重载签名都不冲突。
interface IBox = {
x: number;
y: number;
width: number;
height: number;
}
class Box {
public x: number;
public y: number;
public width: number;
public height: number;
constructor() /* Overload Signature */
constructor(obj: IBox) /* Overload Signature */
constructor(obj?: IBox) /* Implementation Constructor */ {
if (obj) {
this.x = obj.x;
this.y = obj.y;
this.width = obj.width;
this.height = obj.height;
} else {
this.x = 0;
this.y = 0;
this.width = 0;
this.height = 0
}
}
get frame(): string {
console.log(this.x, this.y, this.width, this.height);
}
}
new Box().frame; // 0 0 0 0
new Box({ x:10, y:10, width: 70, height: 120 }).frame; // 10 10 70 120
// You could also write the Box class like so;
class Box {
public x: number = 0;
public y: number = 0;
public width: number = 0;
public height: number = 0;
constructor() /* Overload Signature */
constructor(obj: IBox) /* Overload Signature */
constructor(obj?: IBox) /* Implementation Constructor */ {
if (obj) {
this.x = obj.x;
this.y = obj.y;
this.width = obj.width;
this.height = obj.height;
}
}
get frame(): string { ... }
}
正如chuckj所说,简单的答案是一个可选形参,但是如果我们想用多个形参重载构造函数,或者我们想改变形参顺序,该怎么办呢?
事实证明,构造函数可以像函数一样重载:
class FooBar {
public foo?: number;
public bar?: string;
// Constructor A
constructor(foo: number, bar?: string);
// Constructor B
constructor(bar: string, foo?: number);
// Constructor C
constructor(bar: string);
// Constructor D
constructor(foo: number);
// Constructor E
constructor();
constructor(...args: any[]) {
switch (args.length) {
case 2:
if (typeof args[0] === "number") {
this.foo = args[0];
this.bar = args[1];
} else {
this.bar = args[0];
this.foo = args[1];
}
break;
case 1:
if (typeof args[0] === "number") {
this.foo = args[0];
} else {
this.bar = args[0];
}
}
console.log(this.foo, this.bar);
}
}
const fooBarConstructorA = new FooBar("150", 25);
const fooBarConstructorB = new FooBar(25, "150");
const fooBarConstructorC = new FooBar("150");
const fooBarConstructorD = new FooBar("150");
const fooBarConstructorE = new FooBar();
interface IBox {
x: number;
y: number;
height: number;
width: number;
}
class Box {
public x: number;
public y: number;
public height: number;
public width: number;
constructor(obj: IBox) {
const { x, y, height, width } = { x: 0, y: 0, height: 0, width: 0, ...obj }
this.x = x;
this.y = y;
this.height = height;
this.width = width;
}
}