Hàm tạo (lập trình hướng đối tượng)

Trong lập trình hướng đối tượng dựa trên lớp, **hàm tạo** (tiếng Anh: *constructor*, viết tắt: *ctor*) trong một lớp là một kiểu chương trình con đặc biệt được dùng để tạo ra đối tượng. Nó chuẩn bị đối tượng mới để sử dụng, thường chấp nhận các đối số mà hàm tạo dùng để thiết lập các biến thành viên bắt buộc.

Một hàm tạo có vẻ giống như là phương thức thực thể, nhưng nó khác phương thức vì nó không có kiểu trả về rõ ràng, nó không được  kế thừa ngầm và nó thường có các quy tắc khác nhau để chỉ định tầm vực. Hàm tạo thường có tên giống với lớp được khai báo. Chúng có nhiệm vụ khởi tạo thành viên dữ liệu của đối tượng và thiết lập bất biến của lớp, thất bại nếu bất biến không hợp lệ. Một hàm tạo được viết tốt sẽ cho kết quả đối tượng với trạng thái *hợp lệ*. Đối tượng bất biến phải được khởi tạo trong hàm tạo.

Các lập trình viên cũng hay dùng thuật ngữ *hàm tạo* để chỉ một trong những thẻ đóng gói dữ liệu trong một kiểu dữ liệu đại số. Nó là một cách dùng khác với bài viết này.

Hầu hết các ngôn ngữ cho phép chồng hàm tạo vì vậy một lớp có thể có nhiều hơn một hàm tạo với các tham số khác nhau. Một vài ngôn ngữ còn xem xét một số loại hàm tạo đặc biệt. Hàm tạo, sử dụng một lớp duy nhất để tạo đối tượng và trả về một thực thể mới của lớp đó, được trừu tượng hóa bởi factory, cũng có thể tạo ra đối tượng nhưng với nhiều cách, sử dụng nhiều lớp hay các phương thức phân bổ khác nhau như một vùng chứa đối tượng (*object pool*).

## Các loại hàm tạo
### Hàm tạo tham số

Hàm tạo tham số (*parameterized constructor*) là hàm tạo có kèm theo ít nhất một đối số. Ví dụ:

```cpp
class Example
{
     int x, y;
   public:
     Example();
     Example(int a, int b); // Parameterized constructor
};
Example:: Example()
{
}
Example:: Example(int a, int b)
{
     x = a;
     y = b;
}
```

Khi một đối tượng được khai báo trong hàm tạo tham số, giá trị ban đầu phải được truyền qua như là đối số của hàm tạo. Cách thông thường để khai báo đối tượng có thể không hoạt động. Hàm tạo có thể được gọi tường minh hay ngầm. Phương thức gọi hàm tạo ngầm còn được gọi là phương thức *tốc ký* (*shorthand*).

```cpp
Example e = Example(0, 50); // Explicit call

    Example e(0, 50);           // Implicit call
```


### Hàm tạo mặc định

Nếu lập trình viên không cung cấp hàm tạo cho một lớp, hầu hết mọi ngôn ngữ đều cung cấp một *[[hàm tạo mặc định]]* (*default constructor*).

Hành vi của hàm tạo mặc định phụ thuộc vào ngôn ngữ. Nó có thể khởi tạo các thành viên dữ liệu về số 0 hay giá trị tương đương, hoặc có thể không làm gì.

Một số ngôn ngữ (Java, C#, VB.NET) sẽ mặc định tạo mảng của các kiểu lớp để chứa tham chiếu rỗng. Ngôn ngữ không có tham chiếu rỗng có thể không cho phép xây dựng mặc định các mảng của đối tượng không được xây dựng mặc định, hay yêu cầu khởi tạo tường minh tại thời điểm tạo (C++):


```cpp
#include <iostream>

class student{
    public:
        int a,b;
        student(a=0,b=0)   //default constructor
};

int main() {

}
```


### Hàm tạo sao chép

**Hàm tạo sao chép** (*copy constructor*) định nghĩa các hành động được thực hiện khi trình biên dịch sap chép đối tượng lớp. Một hàm tạo sao chép có một tham số chính thức là kiểu của lớp (tham số đó có thể tham chiếu tới một đối tượng).
Nó được sử dụng để tạo ra một bản sao của một đối tượng có sẵn của cùng lớp. Mặc dù cả hai lớp giống nhau, nó được tính như là một hàm tạo chuyển đổi.

Mặc dù hàm tạo sao chép thường được viết tắt là **copy ctor** hay **cctor**, nó không có liên quan gì đến *hàm tạo lớp* (*class constructor*) được dùng trong .NET dù được viết tắt giống nhau.

### Hàm tạo chuyển đổi

Hàm tạo chuyển đổi (*conversion constructor*) cung cấp một phương tiện cho trình biên dịch để ngầm tạo một đối tượng dựa trên một đối tượng khác không cùng kiểu. Các hàm tạo này thường được ngầm gọi để chuyển các đối số hoặc toán hạng sang một kiểu thích hợp, nhưng chúng cũng có thể được gọi tường minh.

### Hàm tạo di chuyển

Trong C++, hàm tạo di chuyển (*move constructor*) lấy giá trị tham chiếu tới một đối tượng của lớp, và được dùng để hiện thực chuyển quyền sở hữu tài nguyên của đối tượng tham số.

## Cú pháp

* Java, C++, C#, ActionScript, và  có quy ước đặt tên, trong đó hàm tạo cùng tên với tên lớp mà nó liên kết với.
* Trong PHP 5, tên được đề nghị cho hàm tạo là `__construct`. Vì lí do tương thích ngược, một phương thức có cùng tên với lớp sẽ được gọi nếu không tìm thấy phương thức `__construct`. Kể từ PHP 5.3.3, điều này chỉ hoạt động với các lớp không có không gian tên miền (*non-namespaced class*).
* Trong Perl, theo quy ước, hàm tạo được đặt tên "new" và cần phải làm nhiều thứ để tạo đối tượng.
* Trong hệ thống đối tượng Moose của Perl, hàm tạo (được đặt tên *new*) được tạo tự động và mở rộng bằng cách đặc tả một phương thức *BUILD*.
* Trong Visual Basic.NET, hàm tạo được gọi là "`New`".
* Trong Python, hàm tạo được chia thành 2 phương thức, "`__new__`" và "`__init__`". Phương thức `__new__` chịu trách nhiệm phân bổ bộ nhớ cho thực thể và nhận lớp như một đối số (theo quy ước gọi là "`cls`"). Còn phương thức `__init__` (thường gọi là "người khởi tạo" - *initialiser*) được truyền qua thực thể mới tạo ra như là một đối số (theo quy ước gọi là "`self`").
* Hàm tạo trong Object Pascal được biểu thị bằng từ khóa "`constructor`" và có thể có tên do người dùng định nghĩa (nhưng hầu hết được gọi là "`Create`").
* Trong Objective-C, hàm tạo được chia thành 2 phương thức, "`alloc`" và "`init`" với phương thức `alloc` để cấp phát bộ nhớ cho thực thể của lớp, và phương thức `init` xử lý phần lớn việc khởi tạo đối tượng. Một lời gọi tới phương thức "`new`" sẽ gọi tới cả phương thức `alloc` và `init`, với thực thể lớp.

## Ghi chú

## Tham khảo