Lập trình C#

Tính đa hình (Polymorphism) trong C#

Tính đa hình (Polymorphism) trong C#
Được viết bởi Minh Hoàng

Series lập trình C#, ngôn ngữ lập trình hiện đại và mạnh mẽ.

Tính đa hình (Polymorphism) là gì?

Đa hình (Polymorphism) – Theo https://en.wiktionary.org/wiki/polymorphism thì nó là sự kết hợp của Poly https://en.wiktionary.org/wiki/poly là nhiều “many, much” và Morphism https://en.wiktionary.org/wiki/morphism là hình thức, hình dạng “form, shape”. Như vậy, đa hình có nghĩa là nhiều hình thức, hình thái.

Tính đa hình (Polymorphism) trong lập trình hướng đối tượng nói chung, và trong lập trình C# nói riêng cho phép một thao tác có các cách xử lý khác nhau trên các đối tượng khác nhau.
Hay nói cách khác, đây là cơ chế cho phép chúng ta gửi cùng một thông điệp tới nhiều đối tượng thuộc các lớp khác nhau, và mỗi đối tượng đó xử lý riêng theo ngữ cảnh tương ứng của chúng do đó thông điệp của mỗi đối tượng sẽ khác nhau.

Ví dụ: Khi điện thoại có cuộc gọi từ một máy khác, thì tổng đài sẽ báo tín hiệu cho máy đó “rung chuông”, nhưng rung như thế nào: chỉ sáng đèn, hay chỉ rung, chỉ phát nhạc chuông và phát bài gì là tùy vào mỗi chiếc điện thoại, tổng đài không cần quan tâm đến vấn đề này.

– Đa hình gồm có 2 loại:

  1. Đa hình khi chạy (Run-time Polymorphism) – Override.
  2. Đa hình khi biên dịch (Compile-time Polymorphism) – Overload.
1. Đa hình khi chạy (Run-time Polymorphism)
1. Đa hình khi chạy (Run-time Polymorphism)

– Tức là chỉ khi chạy mới biết sử dụng phương thức nào. Để thể hiện được tính đa hình khi chạy thì:

  1. Các lớp phải có quan hệ kế thừa với cùng 1 lớp cha nào đó.
  2. Phương thức đa hình phải được ghi đè (override) ở các lớp con.

Trong phần này sẽ liên quan đến kiến thức:
Tính kế thừa trong lập trình C#.
Lớp trừu tượng Abstract class trong C#.
Override trong lập trình C#.

– Để dễ hiểu, chúng ta sẽ cùng phân tích ví dụ ngay sau đây:

#1. Đầu tiên sẽ tạo class Tau, và 2 class con kế thừa là TauChienTauDuLich đều có method trùng tên là LayThongTin().

[code language=”csharp”] class Tau
{
public void LayThongTin()
{
Console.WriteLine( "Đây là chiếc Tàu." );
}
}

class TauChien : Tau
{
public void LayThongTin()
{
Console.WriteLine( "Đây là Tàu chiến." );
}
}

class TauDuLich : Tau
{
public void LayThongTin()
{
Console.WriteLine( "Đây là Tàu du lịch." );
}
}
[/code]

#2. Tiếp theo trong method Main(), sẽ khai báo 3 đối tượng tàu. Sau đó, gọi các phương thức LayThongTin() của mỗi tàu.

[code language=”csharp” highlight=”6-8″] class MinhHoangBlog
{
static void Main(string[] args)
{
// Khai báo 3 đối tượng tàu
Tau tau1 = new Tau();
Tau tau2 = new TauChien();
Tau tau3 = new TauDuLich();

// Gọi phương thức lấy thông tin
tau1.LayThongTin();
tau2.LayThongTin();
tau3.LayThongTin();
}
}
[/code]

■ Khi chúng ta chạy đoạn code này sẽ được kết quả như sau:

Kết quả chương trình

Kết quả chương trình lần 1


■ Từ kết quả trên ta thấy, khi gọi phương thức LayThongTin(), thì kết quả là giống nhau, đều là “Đây là chiếc Tàu.” mà không phân biệt được phương thức gọi nào là của Tàu, Tàu chiến, hay Tàu du lịch. Do đó, chưa thể hiện được tính đa hình (Polymorphism), vì nếu đúng thì: với cùng một thông điệp là Lấy thông tin, ứng với ngữ cảnh khác nhau(loại tàu khác nhau) thì cần hiển thị ra nội dung thông tin khác nhau.

#3. Để thực hiện, chúng ta sẽ sửa lại đoạn code trên, bằng cách sử dụng thêm từ khóa virtual cho phương thức LayThongTin() ở lớp cha Tàu, và ở 2 lớp con TauChienTauDuLich sẽ thực hiện override phương thức LayThongTin() như sau:

[code language=”csharp” highlight=”3,11,19″] class Tau
{
public virtual void LayThongTin()
{
Console.WriteLine( "Đây là chiếc Tàu." );
}
}

class TauChien : Tau
{
public override void LayThongTin()
{
Console.WriteLine( "Đây là Tàu chiến." );
}
}

class TauDuLich : Tau
{
public override void LayThongTin()
{
Console.WriteLine( "Đây là Tàu du lịch." );
}
}
[/code]

■ Lúc này khi chạy lại method Main() như trên, chúng ta sẽ được kết quả là:

Kết quả chương trình

Kết quả chương trình lần 2

■ Hoặc nếu các bạn sửa lại method Main() với nội dung như sau, thì cũng cho kết quả tương tự:

[code language=”csharp”] class MinhHoangBlog
{
static void Main(string[] args)
{
// Hoặc bạn có thể dùng mảng các tàu như sau:
Tau[] mangTau = new Tau[3];
mangTau[0] = new Tau();
mangTau[1] = new TauChien();
mangTau[2] = new TauDuLich();

for (int ii = 0; ii < 3; ii++)
{
mangTau[ii].LayThongTin();
}
}
}[/code]

■ Qua ví dụ trên chúng ta đã thấy: tính đa hình được thể hiện một cách rõ ràng. Cùng một hành động là lấy thông tin của tàu, nhưng tùy thuộc vào các đối tượng tàu khác nhau mà có cách hành xử (cách xử lý) lấy thông tin là khác nhau.

2. Đa hình khi biên dịch (Compile-time Polymorphism)
2. Đa hình khi biên dịch (Compile-time Polymorphism)

– Tức là khi biên dịch mới biết chương trình biên dịch method overload nào.

Trong phần này sẽ liên quan đến kiến thức:
Overload trong lập trình C#.
Sự khác nhau giữa override và overload trong C#.

– Chúng ta xét một ví dụ nhỏ sau:

[code language=”csharp”] namespace WelcomeTo
{
class MinhHoangBlog
{
static void Main(string[] args)
{
Cat cat1 = new Cat();

Cat cat2 = new Cat( "Tom" );

//…
}
}

class Cat
{
// ①
public Cat() { /* Xử lý abc */ }

// ②
public Cat(string name) { /* Xử lý xyz */ }

//…
}
}
[/code]

■ Ở ví dụ trên, chúng ta thấy: tùy vào chúng ta khởi tạo đối tượng cat1 hay cat2 mà khi biên dịch, chương trình sẽ biên dịch method ① hay method ②.

Cảm ơn bạn đã theo dõi. Đừng ngần ngại hãy cùng thảo luận với chúng tôi!

Giới thiệu

Minh Hoàng

Xin chào, tôi là Hoàng Ngọc Minh, hiện đang làm BrSE, tại công ty Toyota, Nhật Bản. Những gì tôi viết trên blog này là những trải nghiệm thực tế tôi đã đúc rút ra được trong cuộc sống, quá trình học tập và làm việc. Các bài viết được biên tập một cách chi tiết, linh hoạt để giúp bạn đọc có thể tiếp cận một cách dễ dàng nhất. Hi vọng nó sẽ có ích hoặc mang lại một góc nhìn khác cho bạn[...]

2 bình luận

Translate »