Nếu bạn có nền tảng C#, bạn có thể muốn thêm nhiều hàm tạo vào một lớp TypeScript. Mặc dù TypeScript không hỗ trợ nhiều hàm tạo nhưng bạn vẫn có thể đạt được hành vi tương tự
Trong TypeScript, bạn có thể thực hiện hành vi tương tự như việc thêm nhiều hàm tạo bằng cách
- Thêm quá tải hàm tạo VÀ triển khai trình bảo vệ kiểu tùy chỉnh
- Sử dụng phương thức nhà máy tĩnh để xây dựng một lớp
- Thêm một đối số lớp một phần vào hàm tạo
Bài viết này giải thích các giải pháp đó với các ví dụ về mã
Bắt tay vào làm nào 😎
Trong TypeScript, không giống như các ngôn ngữ khác, bạn không thể định nghĩa nhiều hàm tạo bên trong một lớp. Tuy nhiên, bạn có thể đạt được hành vi tương tự bằng cách sử dụng một trong các phương pháp thay thế đó
Làm cách nào để triển khai quá tải hàm tạo?
Một cách để mô phỏng việc thêm nhiều hàm tạo bao gồm
- Xác định quá tải nhiều hàm tạo bên trong một lớp
- Thêm triển khai hàm tạo chính, để nó hỗ trợ quá tải hàm tạo khác
- Kiểm tra các đối số đã truyền bằng trình bảo vệ loại tùy chỉnh
Đây là một ví dụ
typescriptclass MyClass {
private p1: string;
private p2: number = 0;
constructor[p1: string];
constructor[p1: string, p2?: number] {
this.p1 = p1;
if [p2] {
this.p2 = p2;
}
}
}
const cls1 = new MyClass['Tim'];
const cls2 = new MyClass['Tim', 27];
Như bạn có thể thấy, trong ví dụ này, chúng ta khai báo quá tải một hàm tạo và làm cho việc triển khai hàm tạo tương thích với nó
Và đây là một ví dụ phức tạp hơn với ba lần quá tải hàm tạo
typescriptclass MyClass {
public constructor[p1: number];
public constructor[p1: string, p2: string];
public constructor[p1: number, p2: string, p3: string];
public constructor[...arr: any[]] {
if [arr.length === 2] {
console.log['two arguments constructor called.'];
} else if [arr.length === 3] {
console.log['three arguments constructor called.'];
} else if [arr.length === 1] {
console.log['one argument constructor called.'];
}
}
}
Như bạn có thể thấy, việc sử dụng quá tải hàm tạo trong TypeScript có thể nhanh chóng trở nên khó quản lý và khó hiểu. Đó là lý do tại sao tôi thích phương pháp sau tốt hơn
Làm cách nào để sử dụng phương thức xuất xưởng để xây dựng một lớp?
Phương thức xuất xưởng để mô phỏng nhiều hàm tạo đơn giản hơn nhiều trong TypeScript. Nó liên quan đến việc thêm các hàm tĩnh của nhà máy vào lớp sẽ khởi tạo nó bằng các đối số chính xác
Đây là một ví dụ
typescriptclass MyClass {
public p1: string = '';
public p2: number = 0;
public static fromOneValue[p1: string]: MyClass {
const cls = new MyClass[];
cls.p1 = p1;
return cls;
}
public static fromTwoValues[p1: string, p2: number]: MyClass {
const cls = new MyClass[];
cls.p1 = p1;
cls.p2 = p2;
return cls;
}
}
const cls1 = MyClass.fromOneValue['Tim'];
const cls2 = MyClass.fromTwoValues['Tim', 27];
Trong ví dụ này, thay vì thêm quá tải hàm tạo, chúng tôi thêm hai hàm tĩnh của nhà máy để điền vào một thể hiện lớp mới với các đối số chính xác và trả về nó
Phương pháp này đơn giản hơn nhiều để hiểu và duy trì
Làm cách nào để thêm một phần đối số lớp vào hàm tạo?
Cuối cùng, bạn có thể chuyển một phần lớp làm đối số của hàm tạo. Bằng cách đó, bạn có thể chuyển bất kỳ đối số nào bạn muốn cho lớp
Đây là một ví dụ
typescriptclass MyClass {
private p1: string = '';
private p2: number = 0;
constructor[params: Partial] {
Object.assign[this, params];
}
}
const cls1 = new MyClass[{ p1: 'Tim' }];
const cls2 = new MyClass[{ p1: 'Tim', p2: 27 }];
Như bạn có thể thấy, chúng ta có thể truyền bất kỳ đối số nào do lớp định nghĩa cho hàm tạo
Nhược điểm của phương pháp này là vì bạn có thể truyền bất kỳ đối số nào bạn muốn, nên bạn có thể bỏ qua tham số bắt buộc
Phương thức
class Person {
constructor[name] {
this.name = name;
}
introduce[] {
console.log[`Hello, my name is ${this.name}`];
}
}
const otto = new Person["Otto"];
otto.introduce[]; // Hello, my name is Otto
2 là một phương thức đặc biệt của một lớp để tạo và khởi tạo một thể hiện đối tượng của lớp đóGhi chú. Trang này giới thiệu cú pháp
class Person {
constructor[name] {
this.name = name;
}
introduce[] {
console.log[`Hello, my name is ${this.name}`];
}
}
const otto = new Person["Otto"];
otto.introduce[]; // Hello, my name is Otto
2. Đối với thuộc tính class Person {
constructor[name] {
this.name = name;
}
introduce[] {
console.log[`Hello, my name is ${this.name}`];
}
}
const otto = new Person["Otto"];
otto.introduce[]; // Hello, my name is Otto
2 có trên tất cả các đối tượng, xem class Person {
constructor[name] {
this.name = name;
}
introduce[] {
console.log[`Hello, my name is ${this.name}`];
}
}
const otto = new Person["Otto"];
otto.introduce[]; // Hello, my name is Otto
5________số 8
Hàm tạo cho phép bạn cung cấp bất kỳ khởi tạo tùy chỉnh nào phải được thực hiện trước bất kỳ phương thức nào khác có thể được gọi trên một đối tượng được khởi tạo
class Person {
constructor[name] {
this.name = name;
}
introduce[] {
console.log[`Hello, my name is ${this.name}`];
}
}
const otto = new Person["Otto"];
otto.introduce[]; // Hello, my name is Otto
Nếu bạn không cung cấp hàm tạo của riêng mình, thì hàm tạo mặc định sẽ được cung cấp cho bạn. Nếu lớp của bạn là lớp cơ sở, hàm tạo mặc định trống
typescriptclass MyClass {
public constructor[p1: number];
public constructor[p1: string, p2: string];
public constructor[p1: number, p2: string, p3: string];
public constructor[...arr: any[]] {
if [arr.length === 2] {
console.log['two arguments constructor called.'];
} else if [arr.length === 3] {
console.log['three arguments constructor called.'];
} else if [arr.length === 1] {
console.log['one argument constructor called.'];
}
}
}
0Nếu lớp của bạn là lớp dẫn xuất, hàm tạo mặc định sẽ gọi hàm tạo cha, truyền theo bất kỳ đối số nào được cung cấp
typescriptclass MyClass {
public constructor[p1: number];
public constructor[p1: string, p2: string];
public constructor[p1: number, p2: string, p3: string];
public constructor[...arr: any[]] {
if [arr.length === 2] {
console.log['two arguments constructor called.'];
} else if [arr.length === 3] {
console.log['three arguments constructor called.'];
} else if [arr.length === 1] {
console.log['one argument constructor called.'];
}
}
}
1Ghi chú. Sự khác biệt giữa hàm tạo rõ ràng như hàm tạo ở trên và hàm tạo mặc định là hàm tạo mặc định không thực sự gọi trình lặp mảng thông qua trải rộng đối số
Điều đó cho phép mã như thế này hoạt động
typescriptclass MyClass {
public constructor[p1: number];
public constructor[p1: string, p2: string];
public constructor[p1: number, p2: string, p3: string];
public constructor[...arr: any[]] {
if [arr.length === 2] {
console.log['two arguments constructor called.'];
} else if [arr.length === 3] {
console.log['three arguments constructor called.'];
} else if [arr.length === 1] {
console.log['one argument constructor called.'];
}
}
}
2Lớp
class Person {
constructor[name] {
this.name = name;
}
introduce[] {
console.log[`Hello, my name is ${this.name}`];
}
}
const otto = new Person["Otto"];
otto.introduce[]; // Hello, my name is Otto
6 không cần hàm tạo rõ ràng, vì nó không cần thực hiện bất kỳ khởi tạo tùy chỉnh nào. Hàm tạo mặc định sau đó đảm nhận việc khởi tạo biến cha mẹ class Person {
constructor[name] {
this.name = name;
}
introduce[] {
console.log[`Hello, my name is ${this.name}`];
}
}
const otto = new Person["Otto"];
otto.introduce[]; // Hello, my name is Otto
7 từ đối số mà nó được đưa raTuy nhiên, nếu bạn cung cấp hàm tạo của riêng mình và lớp của bạn bắt nguồn từ một số lớp cha, thì bạn phải gọi rõ ràng hàm tạo của lớp cha bằng cách sử dụng
class Person {
constructor[name] {
this.name = name;
}
introduce[] {
console.log[`Hello, my name is ${this.name}`];
}
}
const otto = new Person["Otto"];
otto.introduce[]; // Hello, my name is Otto
8. Ví dụtypescriptclass MyClass {
public constructor[p1: number];
public constructor[p1: string, p2: string];
public constructor[p1: number, p2: string, p3: string];
public constructor[...arr: any[]] {
if [arr.length === 2] {
console.log['two arguments constructor called.'];
} else if [arr.length === 3] {
console.log['three arguments constructor called.'];
} else if [arr.length === 1] {
console.log['one argument constructor called.'];
}
}
}
6Sử dụng
class Person {
constructor[name] {
this.name = name;
}
introduce[] {
console.log[`Hello, my name is ${this.name}`];
}
}
const otto = new Person["Otto"];
otto.introduce[]; // Hello, my name is Otto
9 trên một lớp trải qua các bước sau- [Nếu đó là lớp dẫn xuất] Phần thân của
2 trước lệnh gọiclass Person { constructor[name] { this.name = name; } introduce[] { console.log[`Hello, my name is ${this.name}`]; } } const otto = new Person["Otto"]; otto.introduce[]; // Hello, my name is Otto
8 được đánh giá. Phần này không nên truy cập vàoclass Person { constructor[name] { this.name = name; } introduce[] { console.log[`Hello, my name is ${this.name}`]; } } const otto = new Person["Otto"]; otto.introduce[]; // Hello, my name is Otto
typescript
02 vì nó chưa được khởi tạoclass MyClass { public constructor[p1: number]; public constructor[p1: string, p2: string]; public constructor[p1: number, p2: string, p3: string]; public constructor[...arr: any[]] { if [arr.length === 2] { console.log['two arguments constructor called.']; } else if [arr.length === 3] { console.log['three arguments constructor called.']; } else if [arr.length === 1] { console.log['one argument constructor called.']; } } }
- [Nếu đó là lớp dẫn xuất] Cuộc gọi
8 được đánh giá, khởi tạo lớp cha thông qua cùng một quy trìnhclass Person { constructor[name] { this.name = name; } introduce[] { console.log[`Hello, my name is ${this.name}`]; } } const otto = new Person["Otto"]; otto.introduce[]; // Hello, my name is Otto
- Các trường của lớp hiện tại được khởi tạo
- Phần thân của
2 sau lệnh gọiclass Person { constructor[name] { this.name = name; } introduce[] { console.log[`Hello, my name is ${this.name}`]; } } const otto = new Person["Otto"]; otto.introduce[]; // Hello, my name is Otto
8 [hoặc toàn bộ phần thân, nếu đó là lớp cơ sở] được đánh giáclass Person { constructor[name] { this.name = name; } introduce[] { console.log[`Hello, my name is ${this.name}`]; } } const otto = new Person["Otto"]; otto.introduce[]; // Hello, my name is Otto
Trong phần thân của
class Person {
constructor[name] {
this.name = name;
}
introduce[] {
console.log[`Hello, my name is ${this.name}`];
}
}
const otto = new Person["Otto"];
otto.introduce[]; // Hello, my name is Otto
2, bạn có thể truy cập đối tượng được tạo thông qua typescriptclass MyClass {
public constructor[p1: number];
public constructor[p1: string, p2: string];
public constructor[p1: number, p2: string, p3: string];
public constructor[...arr: any[]] {
if [arr.length === 2] {
console.log['two arguments constructor called.'];
} else if [arr.length === 3] {
console.log['three arguments constructor called.'];
} else if [arr.length === 1] {
console.log['one argument constructor called.'];
}
}
}
02 và truy cập lớp được gọi bằng class Person {
constructor[name] {
this.name = name;
}
introduce[] {
console.log[`Hello, my name is ${this.name}`];
}
}
const otto = new Person["Otto"];
otto.introduce[]; // Hello, my name is Otto
9 đến typescriptclass MyClass {
public constructor[p1: number];
public constructor[p1: string, p2: string];
public constructor[p1: number, p2: string, p3: string];
public constructor[...arr: any[]] {
if [arr.length === 2] {
console.log['two arguments constructor called.'];
} else if [arr.length === 3] {
console.log['three arguments constructor called.'];
} else if [arr.length === 1] {
console.log['one argument constructor called.'];
}
}
}
09. Lưu ý rằng các phương thức [bao gồm getters và setters] và chuỗi nguyên mẫu đã được khởi tạo trên typescriptclass MyClass {
public constructor[p1: number];
public constructor[p1: string, p2: string];
public constructor[p1: number, p2: string, p3: string];
public constructor[...arr: any[]] {
if [arr.length === 2] {
console.log['two arguments constructor called.'];
} else if [arr.length === 3] {
console.log['three arguments constructor called.'];
} else if [arr.length === 1] {
console.log['one argument constructor called.'];
}
}
}
02 trước khi class Person {
constructor[name] {
this.name = name;
}
introduce[] {
console.log[`Hello, my name is ${this.name}`];
}
}
const otto = new Person["Otto"];
otto.introduce[]; // Hello, my name is Otto
2 được thực thi, vì vậy bạn thậm chí có thể truy cập các phương thức của lớp con từ hàm tạo của lớp cha. Tuy nhiên, nếu những phương thức đó sử dụng typescriptclass MyClass {
public constructor[p1: number];
public constructor[p1: string, p2: string];
public constructor[p1: number, p2: string, p3: string];
public constructor[...arr: any[]] {
if [arr.length === 2] {
console.log['two arguments constructor called.'];
} else if [arr.length === 3] {
console.log['three arguments constructor called.'];
} else if [arr.length === 1] {
console.log['one argument constructor called.'];
}
}
}
02, thì typescriptclass MyClass {
public constructor[p1: number];
public constructor[p1: string, p2: string];
public constructor[p1: number, p2: string, p3: string];
public constructor[...arr: any[]] {
if [arr.length === 2] {
console.log['two arguments constructor called.'];
} else if [arr.length === 3] {
console.log['three arguments constructor called.'];
} else if [arr.length === 1] {
console.log['one argument constructor called.'];
}
}
}
02 sẽ chưa được khởi tạo hoàn toàn. Điều này có nghĩa là việc đọc các trường công khai của lớp dẫn xuất sẽ cho kết quả là typescriptclass MyClass {
public constructor[p1: number];
public constructor[p1: string, p2: string];
public constructor[p1: number, p2: string, p3: string];
public constructor[...arr: any[]] {
if [arr.length === 2] {
console.log['two arguments constructor called.'];
} else if [arr.length === 3] {
console.log['three arguments constructor called.'];
} else if [arr.length === 1] {
console.log['one argument constructor called.'];
}
}
}
14, trong khi việc đọc các trường riêng tư sẽ cho kết quả là typescriptclass MyClass {
public constructor[p1: number];
public constructor[p1: string, p2: string];
public constructor[p1: number, p2: string, p3: string];
public constructor[...arr: any[]] {
if [arr.length === 2] {
console.log['two arguments constructor called.'];
} else if [arr.length === 3] {
console.log['three arguments constructor called.'];
} else if [arr.length === 1] {
console.log['one argument constructor called.'];
}
}
}
15typescriptclass MyClass {
private p1: string = '';
private p2: number = 0;
constructor[params: Partial] {
Object.assign[this, params];
}
}
const cls1 = new MyClass[{ p1: 'Tim' }];
const cls2 = new MyClass[{ p1: 'Tim', p2: 27 }];
4Phương thức
class Person {
constructor[name] {
this.name = name;
}
introduce[] {
console.log[`Hello, my name is ${this.name}`];
}
}
const otto = new Person["Otto"];
otto.introduce[]; // Hello, my name is Otto
2 có thể có giá trị trả về. Trong khi lớp cơ sở có thể trả về bất kỳ thứ gì từ hàm tạo của nó, thì lớp dẫn xuất phải trả về một đối tượng hoặc typescriptclass MyClass {
public constructor[p1: number];
public constructor[p1: string, p2: string];
public constructor[p1: number, p2: string, p3: string];
public constructor[...arr: any[]] {
if [arr.length === 2] {
console.log['two arguments constructor called.'];
} else if [arr.length === 3] {
console.log['three arguments constructor called.'];
} else if [arr.length === 1] {
console.log['one argument constructor called.'];
}
}
}
14, nếu không một typescriptclass MyClass {
public constructor[p1: number];
public constructor[p1: string, p2: string];
public constructor[p1: number, p2: string, p3: string];
public constructor[...arr: any[]] {
if [arr.length === 2] {
console.log['two arguments constructor called.'];
} else if [arr.length === 3] {
console.log['three arguments constructor called.'];
} else if [arr.length === 1] {
console.log['one argument constructor called.'];
}
}
}
15 sẽ bị ném ratypescriptclass MyClass {
private p1: string = '';
private p2: number = 0;
constructor[params: Partial] {
Object.assign[this, params];
}
}
const cls1 = new MyClass[{ p1: 'Tim' }];
const cls2 = new MyClass[{ p1: 'Tim', p2: 27 }];
8Nếu hàm tạo của lớp cha trả về một đối tượng, thì đối tượng đó sẽ được sử dụng làm giá trị
typescriptclass MyClass {
public constructor[p1: number];
public constructor[p1: string, p2: string];
public constructor[p1: number, p2: string, p3: string];
public constructor[...arr: any[]] {
if [arr.length === 2] {
console.log['two arguments constructor called.'];
} else if [arr.length === 3] {
console.log['three arguments constructor called.'];
} else if [arr.length === 1] {
console.log['one argument constructor called.'];
}
}
}
02 trên đó các trường lớp của lớp dẫn xuất sẽ được xác định. Thủ thuật này được gọi là , cho phép các trường của lớp dẫn xuất [bao gồm cả trường riêng] được xác định trên các đối tượng không liên quanChỉ có thể có một phương thức đặc biệt với tên
class Person {
constructor[name] {
this.name = name;
}
introduce[] {
console.log[`Hello, my name is ${this.name}`];
}
}
const otto = new Person["Otto"];
otto.introduce[]; // Hello, my name is Otto
2 trong một lớp. Có nhiều hơn một lần xuất hiện phương thức class Person {
constructor[name] {
this.name = name;
}
introduce[] {
console.log[`Hello, my name is ${this.name}`];
}
}
const otto = new Person["Otto"];
otto.introduce[]; // Hello, my name is Otto
2 trong một lớp sẽ gây ra lỗi typescriptclass MyClass {
public constructor[p1: number];
public constructor[p1: string, p2: string];
public constructor[p1: number, p2: string, p3: string];
public constructor[...arr: any[]] {
if [arr.length === 2] {
console.log['two arguments constructor called.'];
} else if [arr.length === 3] {
console.log['three arguments constructor called.'];
} else if [arr.length === 1] {
console.log['one argument constructor called.'];
}
}
}
22. Có một getter hoặc setter được gọi là class Person {
constructor[name] {
this.name = name;
}
introduce[] {
console.log[`Hello, my name is ${this.name}`];
}
}
const otto = new Person["Otto"];
otto.introduce[]; // Hello, my name is Otto
2 cũng là một typescriptclass MyClass {
public constructor[p1: number];
public constructor[p1: string, p2: string];
public constructor[p1: number, p2: string, p3: string];
public constructor[...arr: any[]] {
if [arr.length === 2] {
console.log['two arguments constructor called.'];
} else if [arr.length === 3] {
console.log['three arguments constructor called.'];
} else if [arr.length === 1] {
console.log['one argument constructor called.'];
}
}
}
22class Person {
constructor[name] {
this.name = name;
}
introduce[] {
console.log[`Hello, my name is ${this.name}`];
}
}
const otto = new Person["Otto"];
otto.introduce[]; // Hello, my name is Otto
2 tuân theo cú pháp phương thức bình thường, vì vậy các giá trị mặc định của tham số, tham số còn lại, v.v. tất cả đều có thể được sử dụngclass Person {
constructor[name] {
this.name = name;
}
introduce[] {
console.log[`Hello, my name is ${this.name}`];
}
}
const otto = new Person["Otto"];
otto.introduce[]; // Hello, my name is Otto
6Hàm tạo phải là một tên theo nghĩa đen. Thuộc tính được tính toán không thể trở thành hàm tạo
class Person {
constructor[name] {
this.name = name;
}
introduce[] {
console.log[`Hello, my name is ${this.name}`];
}
}
const otto = new Person["Otto"];
otto.introduce[]; // Hello, my name is Otto
7Đoạn mã này được lấy từ mẫu lớp [bản demo trực tiếp]
class Person {
constructor[name] {
this.name = name;
}
introduce[] {
console.log[`Hello, my name is ${this.name}`];
}
}
const otto = new Person["Otto"];
otto.introduce[]; // Hello, my name is Otto
0class Person {
constructor[name] {
this.name = name;
}
introduce[] {
console.log[`Hello, my name is ${this.name}`];
}
}
const otto = new Person["Otto"];
otto.introduce[]; // Hello, my name is Otto
8 gọi hàm tạo là nguyên mẫu của lớp hiện tại. Nếu bạn thay đổi nguyên mẫu của chính lớp hiện tại, class Person {
constructor[name] {
this.name = name;
}
introduce[] {
console.log[`Hello, my name is ${this.name}`];
}
}
const otto = new Person["Otto"];
otto.introduce[]; // Hello, my name is Otto
8 sẽ gọi hàm tạo của nguyên mẫu mới. Việc thay đổi nguyên mẫu của thuộc tính typescriptclass MyClass {
public constructor[p1: number];
public constructor[p1: string, p2: string];
public constructor[p1: number, p2: string, p3: string];
public constructor[...arr: any[]] {
if [arr.length === 2] {
console.log['two arguments constructor called.'];
} else if [arr.length === 3] {
console.log['three arguments constructor called.'];
} else if [arr.length === 1] {
console.log['one argument constructor called.'];
}
}
}
28 của lớp hiện tại không ảnh hưởng đến lệnh gọi hàm tạo nào của class Person {
constructor[name] {
this.name = name;
}
introduce[] {
console.log[`Hello, my name is ${this.name}`];
}
}
const otto = new Person["Otto"];
otto.introduce[]; // Hello, my name is Otto
8