带有空构造函数的 TypeScript 构造函数重载
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/35998629/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
TypeScript Constructor Overload with Empty Constructor
提问by Daniel Hitzel
Why is it not allowed to have separate constructor
definitions in TypeScript?
To have e.g. two constructors
, I need to write my code like this.
为什么不允许constructor
在TypeScript 中有单独的定义?
要拥有例如两个constructors
,我需要像这样编写代码。
constructor(id: number)
constructor(id: number, name?: string, surname?: string, email?: string) {
this.id = id;
this.name = name;
this.surname = surname;
this.email = email;
}
Thereby I need to put ?
after the parameters that are not required in the first constructor.
因此,我需要将?
第一个构造函数中不需要的参数放在后面。
Why can't I write it like this?
为什么我不能这样写?
constructor(id: number) {
this.id = id;
}
constructor(id: number, name: string, surname: string, email: string) {
this.id = id;
this.name = name;
this.surname = surname;
this.email = email;
}
So that for both constructors all parameters are mandatory.
因此,对于两个构造函数,所有参数都是必需的。
Moreover, if I need to have an empty constructor things get even weirder, since I need to mark every parameter with a ?
.
此外,如果我需要一个空的构造函数,事情会变得更奇怪,因为我需要用?
.
constructor()
constructor(id?: number, name?: string, surname?: string, email?: string) {
this.id = id;
this.name = name;
this.surname = surname;
this.email = email;
}
Why does TypeScriptdiffers from common languages like C#
or Python
here?
为什么TypeScript与像C#
或Python
这里这样的常见语言不同?
I would expect it to work like this.
我希望它像这样工作。
constructor() {
}
constructor(id: number, name: string, surname: string, email: string) {
this.id = id;
this.name = name;
this.surname = surname;
this.email = email;
}
So you can pass none parameter or must pass all parameters.
所以你可以不传递参数或必须传递所有参数。
采纳答案by Aaron Beall
Because your constructor implementation is called by all your overload constructors. (Technically, at runtime there's only one constructor function that gets called with the various overload argument signatures.)
因为您的构造函数实现被所有重载构造函数调用。(从技术上讲,在运行时,只有一个构造函数被各种重载参数签名调用。)
Imagine it like this:
想象一下:
overload_constructor(id:string) {
implementation_constructor(id);
}
implementation_constructor(id:string, name?:string, age?:number) {
// ...
}
Thinking of it this way, overload_constructor
could not call implementation_constructor
unless name
and age
are optional.
以这种方式思考,除非和是可选的,overload_constructor
否则不能调用。implementation_constructor
name
age
Also see Basarat's answer, the implementation isn't exposed for public usage by the type checker (though at runtime it's the "real" constructor used in JS). If you want to only allow ()
, (id)
, or (id, name, surname, email)
as the only valid call signatures you would do it like this:
另请参阅 Basarat 的答案,类型检查器不会公开该实现以供公共使用(尽管在运行时它是 JS 中使用的“真实”构造函数)。如果您只想允许()
, (id)
, 或(id, name, surname, email)
作为唯一有效的调用签名,您可以这样做:
constructor()
constructor(id: number)
constructor(id: number, name: string, surname: string, email: string)
constructor(id?: number, name?: string, surname?: string, email?: string) {
this.id = id;
this.name = name;
this.surname = surname;
this.email = email;
}
Note that in the implementation all parameters are optional, but that signature is not exposed when compiling and you can only use these these calls:
请注意,在实现中,所有参数都是可选的,但编译时不会公开该签名,您只能使用这些调用:
new Foo()
new Foo(1)
new Foo(1, "a", "b", "c")
Not, for example:
不是,例如:
new Foo(1, "a")
回答by basarat
The last function overload is only used in the implementation and not available publicly. This is shown below:
最后一个函数重载只在实现中使用,不公开。这如下所示:
class Foo{
constructor()
constructor(id?: number) {
}
}
const foo1 = new Foo();
const foo2 = new Foo(123); // Error! : not public
If you want id:number
to be available publically ofcourse you can add another overload:
如果你想id:number
公开可用,你可以添加另一个重载:
class Foo{
constructor()
constructor(id: number)
constructor(id?: number) {
}
}
const foo1 = new Foo();
const foo2 = new Foo(123); // Okay
const foo3 = new Foo('hello'); // Error: Does not match any public overload
The reason is that TypeScript tries not to do fancy code generation for function overloading (traditional languages do this using name mangling e.g. C++)
原因是 TypeScript 尽量不为函数重载做花哨的代码生成(传统语言使用名称修饰来做到这一点,例如 C++)
So you can pass none parameter or must pass parameters.
所以你可以不传递参数或必须传递参数。
Actually you can make the final overload optional but none of the public ones as optional. Consider the following example:
实际上,您可以将最终重载设为可选,但不能将公共重载设为可选。考虑以下示例:
class Foo{
constructor(id: number, name:string)
constructor(name:string)
constructor(idOrName?: number|string, name?:string) {
}
}
const foo1 = new Foo('name'); // Okay
const foo2 = new Foo(123); // Error: you must provide a name if you use the id overload
const foo3 = new Foo(123,'name'); // Okay
回答by PeeWee2201
You can use Builder pattern to solve this. Even in C# or Python, it quickly becomes a better approach as the number of constructor arguments grows.
您可以使用 Builder 模式来解决这个问题。即使在 C# 或 Python 中,随着构造函数参数数量的增加,它也很快成为一种更好的方法。
class Foo {
constructor(public id: number, public name: string, public surname: string, public email: string) {
}
static Builder = class {
id: number = NaN;
name: string = null;
surname: string = null;
email: string = null;
Builder() {
}
build(): Foo {
return new Foo(this.id, this.name, this.surname, this.email);
}
}
}
回答by Rodolfo Patane
If you use static methods to implement overload contructors, see.
如果您使用静态方法来实现重载构造函数,请参阅。
export class User implements IUser {
constructor(
private _id: string,
private _name: string,
private _email: string,
) {}
static New(jsonUser:string){
return new User(
JSON.parse(jsonUser).id,
JSON.parse(jsonUser).name,
JSON.parse(jsonUser).email)
}
}