Tải bản đầy đủ (.pdf) (11 trang)

Tài liệu Hướng Đối Tượng Trong C# part 5 docx

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (154.61 KB, 11 trang )




Construction and Disposal
Constructor :
Cú pháp khai báo một Constructor là : chúng ta khai báo một phương thức mà cùng tên
với lớp và không có kiểu trả về.
public class MyClass
{
public MyClass()
{
}
// rest of class definition
Như trong c++ và java, bạn có thể không cần định nghĩa constructor trong lớp của bạn
nếu không cần thiết. Nếu bạn không định nghĩa một constructor nào trong lớp của bạn thì
trình biên dịch tạo một constructor mặc định để khởi tạo một số giá trị mặc định như: gán
chuỗi rỗng cho chuỗi, gán 0 cho kiểu số, false cho kiểu bool.
Các contructor theo cùng luật overloading như các phương thức khác. Bạn cũng có thể
t
ạo nhiều constructor cùng tên và khác tham số giống như các phương thức nạp chồng :
public MyClass() // zero-parameter constructor
{
// construction code
}
public MyClass(int number) // another overload
{
// construction code
}
Chú ý : khi bạn đã định nghĩa một constructor trong lớp của bạn thì trình biên dịch sẽ
không tự động tạo ra constructor mặc định.
Chúng ta có thể định nghĩa các constructor với các bổ từ private và protected để chúng


không thể được nhìn thấy trong các lớp không có quan hệ:
public class MyNumber
{
private int number;
private MyNumber(int number) // another overload
{
this.number = number;
}
}
Chú ý: Nếu bạn định nghĩa một hay nhiều constructor private thì những lớp thừa kế lớp
của bạn sẽ không thể khởi tạo được. Do đó chúng ta phải cân nhắc kỹ lưỡng khi định
nghĩa bổ từ của một constructor.
Constructor tĩnh(static):
Chúng ta định nghĩa một constructor tĩnh để khởi tạo giá trị cho các biến tĩnh.
class MyClass
{
static MyClass()
{
// initialization code
}
// rest of class definition
}
Một nguyên nhân để viết một constructor tĩnh là: Nếu lớp của bạn có một số trường hay
thuộc tính cần được khởi tạo từ bên ngoài trước khi lớp được sử dụng lần đầu tiên.
Chúng ta không thể biết chắc được khi nào một constructor tĩnh sẽ được thực hiện. Và
chúng ta cũng không biết trước các constructor tĩnh của các lớp khác nhau sẽ thực hiện
những gì. Nhưng chúng ta có thể chắ
c chắn rằng constructor tĩnh chỉ chạy một lần và nó
sẽ được gọi trước khi đoạn mã của bạn tham khảo đến lớp đó. Trong C#, Constructor tĩnh
thường được thực hiện ngay trước lần gọi đầu tiên của một thành viên trong lớp đó.

Constructor tĩnh không có bổ từ truy cập, không có bất kỳ một tham số nào và chỉ có duy
nhất một constructor tĩnh trong một lớp.
Chúng ta có thể đị
nh nghĩa một constructor tĩnh và một constructor thực thể không có
tham số trong cùng một lớp. Nó không gây ra bất kỳ một sự xung đột nào bởi vì
constructor tĩnh được thực hiện khi lớp được khởi tạo còn constructor thực thể được thực
hiện khi một thực thể được tạo ra.
Gọi các constructor từ những constructor khác:
Xét ví dụ như sau:
class Car
{
private string description;
private uint nWheels;
public Car(string model, uint nWheels)
{
this.description = description;
this.nWheels = nWheels;
}

public Car(string model)
{
this.description = description;
this.nWheels = 4;
}
// etc.

Ta thấy cả hai constructor đều khởi tạo cùng các trường, và nó sẽ ngắn gọn hơn nếu ta chỉ
cần viết đoạn mã ở một constructor. C# cho phép ta làm đều đó như sau:
class Car
{

private string description;
private uint nWheels;

public Car(string model, uint nWheels)
{
this.description = description;
this.nWheels = nWheels;
}

public Car(string model) : this(model, 4)
{
}
// etc
Khi ta khởi tạo một biến như sau:
Car myCar = new Car("Proton Persona");
Thì constructor 2 tham số sẽ được thực thi trước bất kỳ đoạn mã nào trong constructor 1
biến.
Constructor của các lớp thừa hưởng:
Khi chúng ta tạo ra một thể hiện của một lớp thừa hưởng thì không phải chỉ những
constructor của lớp thừa hưởng đó được thực hiện mà cả những constructor của lớp cơ sở
cũng được gọi. Và các constructor của lớp cơ sở
sẽ được thực hiện trước khi các
constructor của lớp thừa hưởng.
Chúng ta xét ví dụ sau:
abstract class GenericCustomer
{
private string name;
// lots of other methods etc.
}


class Nevermore60Customer : GenericCustomer
{
private uint highCostMinutesUsed;
// other methods etc.
}
Đều chúng ta cần ở ví dụ trên là khi một thể hiện của lớp Nevermore60Customer được
tạo ra thì thuộc tính name phải được khởi tạo giá trị null và thuộc tính
highCostMinutesUsed được khởi tạo là 0.
GenericCustomer arabel = new Nevermore60Customer();
Đối với thuộc tính highCostMinutesUsed thì không có vấn đề gì, nó sẽ được constructor
mặc định khởi tạo giá trị 0. Còn thuộc tính name thì sao? Lớp con không thể truy cập vào
thuộc tính này bởi vì nó được khai báo private. Nhưng trên thực tế thì thuộc tính này luôn
được khởi tạo giá trị null vì khi này constructor của lớp cơ sở cũng được gọi và nó thực
hiện trước khởi tạo giá trị null cho thuộc tính name.
Thêm một constructor không tham số trong một quan hệ th
ừa kế:
Chúng ta sẽ xem xét chuyện gì sẽ xảy ra nếu ta thay thế constructor mặc định bằng một
constructor khác không có tham số. Xét ví dụ ở trên, bây giờ ta muốn khởi tạo name bằng
giá trị <noname> ta làm như sau:
public abstract class GenericCustomer
{
private string name;

public GenericCustomer()
: base() // chúng ta có thể xoá bỏ dòng này mà không có ảnh hưởng gì khi biên dịch
{
name = "<no name>";
}

Điểm chú ý ở đây là chúng ta thêm lời gọi tường minh đến constructor của lớp cơ sở

trước khi constructor của lớp GenericCustomer được thực hiện và chúng ta sử dụng từ
khoá base để gọi các constructor ở lớp cơ sở.
Trên thực tế chúng ta có thể viết như sau:
public GenericCustomer()
{
name = "<no name>";
}
Nếu trình biên dịch không thấy bất kỳ một sự tham khảo nào đến các constructor khác thì
nó sẽ nghĩ là chúng ta muốn gọi constructor mặc định của lớp cơ sở.
Chú ý: Từ khoá base và this chỉ cho phép dùng để gọi một constructor khác, nếu không
nó sẽ báo lỗi.
Nếu chúng ta khai báo như sau:
private GenericCustomer()
{
name = "<no name>";
}
Thì khi khởi tạo một thể hiện của lớp thừa hưởng neverMore60Customer trình biên dịch
sẽ báo lỗi :
'Wrox.ProCSharp.OOCSharp.GenericCustomer.GenericCustomer()' is inaccessible due
to its protection level
Bởi vì bạn đã khai báo private nên lớp con sẽ không nhìn thấy constructor này nên sẽ báo
lỗi.

×