Constructor và tính kế thừa trong C#
Originally published at http://www.iceteaviet.com on December 20th, 2016
Hôm nay nhân lúc đang làm đồ án môn Thiết kế phần mềm, cần sử dụng OOP, inheritance,.. khá nhiều, mình xin viết một article nho nhỏ về hàm dựng (constructor) trong tính kế thừa của C#.
Theo nguyên tắc, khi khởi tạo đối tượng của lớp con, thì hàm dựng (constructor) của lớp cha sẽ được gọi trước, sau đó mới tới đổi tượng của lớp con.
Ví dụ mình có class Base và Child kế thừa từ lớp Base như sau:
Thì khi Run, chương trình sẽ cho kết quả như sau:
Rõ ràng constructor của lớp Base đã được gọi trước!
Chúng ta có thể kiểm tra các trường hợp khác:
- Cho lớp Base thành abstract.
- Sửa lại hàm Main, khởi tạo đối tượng bằng
Child c = new Child();
Tất cả đều cho kết quả tương tự.
Tiếp tục thử một trường hợp đặc biệt khác, thêm một constructor mới chứa tham số vào class Base và Child như sau:
Run chương trình, chúng ta được kết quả sau:
Ở đây, dù chúng ta tạo đối tượng với constructor có tham số, thì constructor mặc định (constructor không tham số) của lớp Base luôn được gọi.
Bây giờ nếu xóa đi constructor mặc định của lớp Base và Run chương trình thì sẽ bị lỗi ngay lập tức.
Từ đó ta rút ra các kết luận sau
Khi một class được tạo ra, nếu class đó chưa có constructor, C# sẽ tự động generate một constructor mặc định (constructor không tham số)
Vì nếu không làm vậy chúng ta sẽ không thể tạo một object mới thuộc class đó rồi. Tuy nhiên nếu tạo thêm một constructor khác (có tham số), và xóa constructor mặc định đi, thì C# sẽ cho rằng class của bạn từ giờ đã có thể tự tạo một object mới và sẽ không generate constructor mặc định nữa. Điều đó đồng nghĩa với việc các object được tạo bằng cách gọi new Base()
sẽ lỗi.
Ngoài ra, khi khởi tạo một đối tượng lớp con Child, thì C# sẽ automatically gọi constructor mặc định của lớp cha Base trước, sau đó mới gọi constructor của lớp con.
Tại sao lại như vậy?
Theo mình, cứ tưởng tượng lớp con là một “cụ thể hóa” của một lớp cha.
Giống như một chiếc xe máy, trước khi thành một chiếc xe nó phải qua công đoạn lắp ráp khung xe, thì KhungXe đó chính là lớp cha. Mà để tạo khung xe thì phải dùng constructor của KhungXe, trong đó sẽ gọi các hàm ráp, hàn, bắt ốc,.. Sau khi đã xong phần khung xe, ta gọi constructor của XeMay gọi các hàm gắn bánh, gắn yên xe,.. giúp tạo thành một chiếc xe hoàn chỉnh!
Vậy thứ tự gọi thực sự logic và thực tế đúng không nào?
Tuy nhiên nếu muốn gọi constructor có tham số cụ thể của lớp cha theo ý của mình, bạn cần sử dụng tự khóa “base()” như sau:
Minh xin nói luôn một cách tổng quát, trong Java thì hàm dựng của lớp cha cũng sẽ tự động được gọi khi khởi tạo đối tượng của lớp con. Các bạn có thể tham khảo tại đây.
Cuối cùng, mình có một câu hỏi cho các bạn, có cách nào để tạo một đối tượng thuộc lớp con mà không cần gọi hàm dựng (constructor) của lớp cha không? Hãy comment trả lời bên dưới nhé.
Happy coding~