Lập trình hướng đối tượng trong C#

  • In C#
  • Tuesday, August 09, 2016
  • 1315 Views

Lập trình hướng đối tượng là phương pháp lập trình thay vì tập trung vào việc phân tích và thực hiện các chức năng (thủ tục) của chương trình thì chúng ta tiến hành tìm hiểu, phân tích các thực thể, các đối tượng tham gia vào chương trình. Từ đó chúng thực hiện xây dựng các đặc trưng, các hành vi của các đối tượng. Và chương trình chẳng qua là mô phỏng các tương tác giữa các đối tượng đó mà thôi.

1. Lập trình hướng đối tượng là gì
- Lập trình hướng đối tượng là phương pháp lập trình thay vì tập trung vào việc phân tích và thực hiện các chức năng (thủ tục) của chương trình thì chúng ta tiến hành tìm hiểu, phân tích các thực thể, các đối tượng tham gia vào chương trình. Từ đó chúng thực hiện xây dựng các đặc trưng, các hành vi của các đối tượng. Và chương trình chẳng qua là mô phỏng các tương tác giữa các đối tượng đó mà thôi.
- Phương pháp lập trình hướng đối tượng tạo ra nhiều cái ưu điểm ưu việt hơn so với phương pháp lập trình thủ tục. Một trong những ưu điểm lớn nhất của phương pháp lập trình hướng đối tượng là khả năng sử dụng lại code (reuse code). 

2. Các khái niệm thiết yếu trong lập trình hướng đối tượng
- Đối tượng (object): là những sự vật, sự việc, hiện tượng xảy ra trong thế giới thực mà con người có thể nhìn thấy, sờ thấy, cảm nhận thấy. Một số VD về các đối tượng: đồng hồ treo tường, máy chiếu, bàn học, bức tranh, học viên Nguyễn Văn Mạnh, …..
- Lớp (class): là một mẫu (template) hoặc là một plan (kế hoạch) cho việc xây dựng các đối tượng. Lớp là một sự trừu tượng hóa của các đối tượng có chung đặc trưng và hành vi. Một số VD về lớp: Bàn, Học viên, Nhân viên, ….
Một đối tượng là một thể hiện cụ thể của một lớp.
- Đặc trưng (characteristic): là những tính chất của các đối tượng. VD: màu sắc, chiều dài, chiều rộng, tuổi, địa chỉ ….
Mặc định thì các đặc trưng là private.
- Hành vi (behavior): là những hành động của đối tượng. VD: các hành vi của Sinh viên: đăng ký học tiếng Anh, nhảy, diễn thuyết, trình bày báo cáo tốt nghiệp…
Mặc định các hành vi là public.
- Kế thừa (inheritance): là một cơ chế cho phép các đối tượng có thể kế thừa tất cả những đặc trưng và hành vi của các đối tượng khác. VD: một nhân viên kế thừa tất cả các đặc trưng của một người. Một trưởng phòng kế thừa tất cả các đặc trưng của một nhân viên.
- Tính đóng gói (encapsulation): là khả năng một đối tượng có thể che dấu tất cả các đặc trưng cũng như các hành vi của họ bên trong 1 lớp.
- Tính đa hình (polymorphism): là khả năng một hành vi của một đối tượng có thể được thực hiện dưới nhiều hình thức khác nhau.
- Tính trừu tượng (abstraction): là khả năng cho phép thực hiện trừu tượng hóa tất cả các đối tượng trong thế giới thực với những hành vi và đặc trưng chung vào trong lập trình và cho phép tạo ra các lớp mà có thể được kế thừa.

3. Các bước thực hiện tiếp cận phương pháp lập trình hướng đối tượng
- Phân tích đặc tả của bài toán lập trình để tìm ra các đối tượng, các lớp.
Để tìm được các đối tượng, các lớp chúng ta dựa vào các danh từ hoặc cụm danh từ trong đặc tả bài toán.
VD: áp dụng đặc tả bài toán PCS_Lab5 trong buổi trước chúng ta tìm ra các danh từ, cụm danh từ sau:
Chương trình, Sinh viên, Chức năng, Menu, Mục chọn (MenuItem),…..
- Tìm ra các hành vi, các đặc trưng của các đối tượng.
VD: đối tượng Menu có các đặc trưng và các hành vi sau:
+ Các đặc trưng:

  • Danh sách các mục chọn.
  • Mục được chọn.

+ Các hành vi:

  • Hiển thị.
  • Thêm mục chọn.
  • Bớt mục chọn.

……………………………… 
- Tìm ra mối quan hệ, sự kết hợp, tương tác giữa các đối tượng.
- Tiến hành viết code để xây dựng chương trình.

4. Thực hiện lập trình hướng đối tượng trong C#
- Để thực hiện lập trình hướng đối tượng thì việc đầu tiên chúng ta phải xác định và tạo ra các lớp (class).
- Để tạo ra một lớp trong C# chúng ta thực hiện như sau:

  • Click phải chuột vào Project chọn Add -> Class.
  • Gõ tên lớp.
  • Nhấn OK.

Cú pháp khai báo 1 lớp trong C#:
[bổ từ truy cập] class [tên lớp]
{
}

Trong đó: 
[bổ từ truy cập]: là từ khóa để chỉ ra phạm vi truy cập của lớp. Các phạm vi truy cập của lớp có thể là 1 trong các phạm vi sau:

  • public
  • internal
  • private

[tên lớp]: tuân theo quy tắc định danh.
VD: để khai báo lớp Menu chúng ta sử dụng đoạn code.

public class Menu
{
}

- Các thành phần của một lớp (members of class):
Một lớp có thể có 4 thành phần:

  • Các biến để lưu trữ các đặc trưng của đối tượng (variables).

Cú pháp để khai báo các đặc trưng của đối tượng:
[bổ từ truy cập] [kiểu dữ liệu] [tên biến];

Trong đó:
[bổ từ truy cập]: chỉ ra phạm vi truy cập của biến. Các phạm vi có thể:

  • private: một biến được chỉ ra private chỉ có thể được truy cập bởi các thành phần trong lớp đó.
  • protected: một biến được khai báo là protected chỉ có thể được truy cập bởi các thành phần bên trong lớp đó và các thành phần trong lớp kế thừa lớp đó.
  • internal: một biến internal có thể được truy cập bởi các thành phần trong 1 lớp, các thành phần trong lớp kế thừa, các thành phần trong các lớp cùng assembly với nó.
  • public: một biến là public thì có thể được truy cập bởi bất kì một thành phần của bất kì một lớp nào.

[kiểu dữ liệu]: là bất kì các kiểu dữ liệu nào được hỗ trợ bởi C#.
[tên biến]: tuân theo quy tắc định danh.
VD: về khai báo các biến.

private int _mucChon;
private ArrayList _danhSachMucChon;
  • Các phương thức (methods): là những đoạn code mô phỏng các hành vi của các đối tượng trong lớp.

Cú pháp khai báo phương thức:
[bổ từ truy cập] [kiểu dữ liệu trả về] [tên phương thức] ([danh sách các đối số])
{
[các câu lệnh];
}

Trong đó:
[bổ từ truy cập]: giống với của biến.
[kiểu dữ liệu trả về]: chỉ ra kiểu của giá trị được trả về bởi phương thức, nếu phương thức ko trả về giá trị thì kiểu dữ liệu trả về là void.
[tên phương thức]: tuân theo quy tắc định danh.
[danh sách đối số]: là danh sách các khai báo biến cách nhau bởi dấu phẩy (,).
VD:

public int HienThi()
{
Console.WriteLine("CAC CHUC NANG CHINH CUA CHUONG TRINH");
for (int i = 0; i < _danhSachMucChon.Count; i++)
{
Console.WriteLine("{0}. {1}", i + 1, _danhSachMucChon[i]);
}
Console.Write("Ban chon: ");

int chon;
do
{
chon = int.Parse(Console.ReadLine());
}
while (chon<1 || chon>_danhSachMucChon.Count);

return chon;
}

5. Kế thừa (Inheritance)- Kế thừa là một cơ chế cho phép một lớp có tất cả các đặc trưng và hành vi của một lớp khác.
- Kế thừa là một hình thức cho phép chúng ta sử dụng lại code.
- Kế thừa cho phép chúng ta xây dựng các ứng dụng mà ko phải viết code từ đầu, giúp tiết kiệm thời gian, chi phí bỏ ra để xây dựng các ứng dụng.
- Trong C# để thực hiện kế thừa chúng ta dùng cú pháp:
[bổ từ truy cập] class [tên lớp] : [tên lớp được kế thừa]
- Các khái niệm có liên quan đến kế thừa:

  • Lớp cha (parent class): là lớp được kế thừa (là lớp có tất cả các hành vi, các đặc trưng được kế thừa), lớp cha còn được gọi là super class hoặc base class (lớp cơ sở).
  • Lớp con (child class): là lớp kế thừa tất cả các đặc trưng và hành vi của các lớp khác, lớp con còn được gọi là sub class hoặc derive class (lớp dẫn xuất).

- Một số chú ý về kế thừa trong C#:

  • Trong C# chúng ta chỉ có thể kế thừa từ 1 lớp (đơn kế thừa đối với lớp).
  • Tuy nhiên chúng ta có thể đa kế thừa đối với giao tiếp (Interface).


6. Tính đa hình (Polymorphism)
- Tính đa hình là khả năng cho phép một hành vi (một phương thức) có thể được thể hiện dưới nhiều hình thức khác nhau.
- Trong C# tính đa hình có thể được cài đặt theo 2 cách:

  • Overloading method (quá tải hàm): là khả năng trong một lớp có thể có nhiều phương thức trùng tên với nhau. Có 2 hình thức quá tải hàm:
+ Các hàm trùng tên và số lượng các đối số là khác nhau.
+ Các hàm trùng tên và số lượng các đối số bằng nhau nhưng kiểu dữ liệu của một số các đối số là khác nhau.
  • Overidding method (chồng hàm): là khả năng cho phép các lớp con có thể có các phương thức trùng tên với lớp cha.

Để thực hiện chồng hàm thì các hành vi của lớp cơ sở cần phải được đánh dấu bằng từ khóa virtual.
Còn các lớp kế thừa từ lớp cơ sở này muốn thực hiện tính đa hình cho hành vi trên thì phải dùng từ khóa override. 

7. Lớp trừu tượng (abstract class)
- Lớp trừu tượng là một lớp được sử dụng để chia sẻ tất cả những hành vi và đặc trưng cho các lớp khác sử dụng. 
- Chúng ta ko thể tạo một thể hiện trực tiếp từ một lớp trừu tượng. Muốn tạo ra thể hiện của lớp trừu tượng thì chúng ta phải tạo ra một lớp kế thừa từ lớp trừu tượng.
- Trong C# thì một lớp trừu tượng được đánh dấu bởi từ khóa abstract.

8. Lớp đóng kín (sealed class)
- Lớp đóng kín là lớp mà ko thể có lớp kế thừa.
- Lớp đóng kín được đánh dấu bởi từ khóa sealed.
- Lớp đóng kín thường là lớp được sử dụng để cung cấp các chức năng tiện ích. Những lớp này thường được gọi là Utilities Classes.

9. Giao tiếp (interface)
- Giao tiếp là một tập hợp các thuộc tính và các hành vi cần được thực hiện bởi một lớp nào đó.
- Giao tiếp được sử dụng như một khế ước (giao kèo) để đảm bảo rằng một lớp phải thực hiện những hành vi nhất định nào đó.
- Trong C# thì giao tiếp được đánh dấu bởi từ khóa interface.
- Trong giao tiếp thì các thuộc tính và các hành vi ko được thực hiện (ko có code thực hiện).
- Một lớp trong C# có thể kế thừa nhiều giao tiếp.

10. Không gian tên (namespace)
- Namespace là một phần tử trong chương trình C# cho phép tổ chức các lớp, các giao tiếp, các cấu trúc.
- Namespace giúp cho việc tránh sự xung đột giữa các lớp, các giao tiếp, các cấu trúc (tránh sự trùng lặp tên) trong C#.
- Namespace giúp cho việc cấu trúc các thư viện, tổ chức nó thành dạng có thứ bậc (phân cấp) dễ dàng cho việc quản lý các lớp, các giao tiếp và các cấu trúc trong chương trình C#.
- Các namespace có thể lồng nhau (một namespace có thể nằm trong một namespace khác).
- Khi chúng ta tạo một Project trong VS.NET 2005 thì nó luôn tạo cho chúng ta một namespace mặc định có tên trùng với tên Project cho tất cả các cấu trúc, các lớp, các giao tiếp.
- Một namespace được khai báo bởi từ khóa namespace.
Cú pháp tổng quát để khai báo namespace:
namespace [tên của namespace]
{
[danh sách các lớp, các giao tiếp, các cấu trúc];
}

- Các namespace ko có bổ từ truy cập, mặc định bổ từ truy cập của các namespace luôn là public.
- Nếu trong Project chúng ta ko khai báo namespace cho các lớp thì các lớp đó thuộc về namespace mặc định (default namespace).
- Để thay đổi namespace mặc định của Project chúng ta click phải chuột vào Project chọn Properties sau đó gõ tên namespace mặc định cho Project ở mục Default Namespace.
- Qui ước cho việc đặt tên namespace (ko bắt buộc):
Tên namespace bao gồm 3 phần cách nhau bởi dấu chấm (.)
[Tên tổ chức].[tên ứng dụng].[tên module]

VD: đặt tên cho một ứng dụng quản lý nhân sự ở Aptech.

Aptech.EMS.Entities
Aptech.EMS.DAL

- Namespace là một cách tổ chức logic các lớp.
- Sử dụng namespace như thế nào?
Khi chúng ta muốn sử dụng các lớp, các cấu trúc, các giao tiếp trong một namespace thì chúng ta có 3 cách:

  • Gõ tên đầy đủ của namespace chứa lớp và tên lớp. VD: để sử dụng lớp Employee trong namespace Aptech.EMS.Entities thì chúng ta sử dụng như sau:

Aptech.EMS.Entities.Employee.
Cách sử dụng như trên được gọi là fully qualified name.

  • Sử dụng từ khóa using để khai báo namespace chứa thư viện các lớp, các giao tiếp, các cấu trúc.

VD: để sử dụng lớp Employee trong namespace Aptech.EMS.DAL chúng ta sử dụng:
using Aptech.EMS.DAL;
Employee e1 = new Employee();
Cách thứ hai được gọi là unqualified name.

  • Sử dụng bí danh cùng với từ khóa using. using dal = Aptech.EMS.DAL;

using ent = Aptech.EMS.Entities;
dal.Employee e2 = new dal.Employee();
ent.Employee e3 = new ent.Employee();
- Tập hợp thư viện lớp của .NET Framework cũng được Microsoft tổ chức thành các namespace. VD: chúng ta có một số namespace cơ bản như sau:

  • System: là namespace chứa các lớp thao tác với hệ thống.
  • System.IO: là namespace chức các lớp thực hiện thao tác vào ra dữ liệu trên tệp tin.
  • System.Windows.Form: là namespace chứa các lớp cho phép tạo và quản lý các cửa sổ trong ứng dụng Window Form.
  • System.Data: là namespace chứa các lớp thực hiện thao tác với dữ liệu.
  • System.Diagnostics: chứa các lớp cho phép thực hiện theo dõi và chuẩn đoán lỗi của ứng dụng.
  • ……..

11. Xử lý ngoại lệ (Exception Handling)
- Exception (ngoại lệ): là bất kì sự bất thường nào xảy ra ko mong muốn trong ứng dụng. 
- Một ứng dụng tốt thì cần phải giải quyết được tất cả các ngoại lệ có thể xảy ra.
- Các kiểu ngoại lệ: có 2 kiểu ngoại lệ trong C#.

  • Các ngoại lệ ở mức hệ thống: các ngoại lệ này là những ngoại lệ được quăng ra (thrown) bởi hệ thống và thường là các nguyên nhân do hệ thống gây ra VD như thiếu bộ nhớ, kết nối mạng bị ngắt, phần cứng bị lỗi….
  • Các ngoại lệ mức ứng dụng: là các ngoại lệ được quăng ra bởi người viết ứng dụng.

- Tất cả các ngoại lệ trong C# đều trực tiếp hoặc gián tiếp kế thừa từ một lớp là Exception. Lớp này nằm trong namespace System.
- Lớp Exception có các thuộc tính sau:

  • Message: Lưu trữ thông điệp chỉ ra nguyên nhân của ngoại lệ.
  • Source: chỉ ra tên của ứng dụng hoặc tên của đối tượng gây ra ngoại lệ.
  • StackTrace: cung cấp thông tin chi tiết về ngoại lệ trên Stack vào thời điểm mà nó được quẳng ra.
  • InnerException: trả về thể hiện của ngoại lệ gây ra ngoại lệ hiện tại.
- Cú pháp tổng quát để bắt ngoại lệ:
try
{
[đoạn lệnh mà có khả năng xảy ra ngoại lệ];

catch ([kiểu ngoại lệ] [tên đối tượng ngoại lệ])
{
[đoạn lệnh để xử lý ngoại lệ];
}
finally
{
[đoạn lệnh được thực hiện cả trong 2 trường hợp xảy ra hoặc ko xảy ra ngoại lệ];
}

- Một try có thể có nhiều catch.
- Một ngoại lệ có thể được quăng ra bởi từ khóa throw.
- Để tạo ra một ngoại lệ thì chúng ta phải tạo ra một lớp kế thừa từ lớp Exception.

12. Delegate (chuyển giao)
- Delegate (chuyển giao): chuyển giao là các đối tượng chứa các tham chiếu đến các phương thức thay vì chứa tên phương thức thực tế. Chuyển giao trong C# giống với con trỏ hàm trong C.
- Chuyển giao là một đối tượng cho phép chúng ta thực hiện một cuộc gọi phương thức bất kì vào thời điểm mà chương trình đang thực hiện (runtime). Hình thức này được gọi dynamic calling. 
- Để thực hiện khai báo một chuyển giao chúng ta sử dụng từ khóa delegate. Một delegate là một đối tượng tham chiếu đến một phương thức chính vì vậy khi khai báo delegate là chúng ta thực hiện khai báo khuôn dạng của phương thức mà delegate tham chiếu đến.
- Cú pháp khai báo 1 delegate:
[bổ từ truy cập] delegate [tên delegate] (danh sách các tham số);
VD: khai báo một delegate cho phép tham chiếu đến tất cả các hàm có 2 đối số nguyên và trả về một số nguyên.
public delegate int PhepTinhDelegate (int a, int b);

13. Event (sự kiện)
- Sự kiện: là một tín hiệu được thông báo giữa các đối tượng. Sự kiện xảy ra khi có sự tương tác giữa các đối tượng trong hệ thống. Sự kiện là các kích thích xảy ra bên trong hoặc bên ngoài hệ thống. 
- Các bước tạo và sử dụng sự kiện trong C#.
Để tạo sự kiện trong C# thì đầu tiên chúng ta phải tạo một delegate để cho phép tham chiếu đến các phương thức mà thực hiện tương tác lại các sự kiện (đáp ứng khi các sự kiện xảy ra).
// Khai bao delegate.
public delegate void ViecMoiDelegate(string viec);
Khai báo sự kiện: sử dụng từ khóa event.
Cú pháp tổng quát:
[bổ từ truy cập] event [tên delegate] [tên sự kiện];

VD:

public event ViecMoiDelegate OnViecLamMoi = null;
Khai báo hàm được sử dụng để phát ra sự kiện:
public void ThongBao(string viec)
{
// Kiem tra xem su kien da duoc dang ky chua neu dang ky roi thi phat ra su kien 
// do.
if (OnViecLamMoi != null)
OnViecLamMoi(viec);
}

Các đối tượng đăng ký sự kiện (các đối tượng này được gọi là subcribers).
Để đăng ký sự kiện chúng ta sử dụng cú pháp += như sau:


// 4. Dang ky nhan su kien cua cong ty moi gioi.
ctyMoiGioi.OnViecLamMoi += new ViecMoiDelegate(NhanThongBao);
Phát ra sự kiện:
ctyA.ThongBao("Ki su phan mem tai cty B");