Lập trình C#

Lớp trừu tượng Abstract class trong C#

Lớp trừu tượng Abstract class trong lập trình 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ẽ.

Lớp trừu tượng Abstract class trong C#

Lớp trừu tượng – abstract class là một trong những khái niệm quan trọng trong lập trình hướng đối tượng. Bài viết này sẽ giới thiệu đến các bạn các vấn đề liên quan đến khái niệm này với những nội dung sau:

  1. Abstract class là gì?
  2. Cách khai báo lớp và phương thức trừu tượng
  3. Các đặc điểm của lớp và phương thức trừu tượng
  4. Ví dụ minh họa cho đặc điểm của lớp và phương thức trừu tượng
  5. Sự khác nhau của abstract method và virtual method
1. Abstract class là gì?
1. Abstract class là gì?

Abstract class hay còn gọi là lớp trừu tượng. Nếu dùng từ trừu tượng (dịch nghĩa của từ abstract) thì sẽ gây cho bạn khó hiểu, có gì đó mơ hồ khi mới tiếp cận, do đó từ bên dưới mình sẽ gọi lớp trừu tượng là abstract class, phương thức trừu tượng là abstract method. Bạn cứ hiểu nó cũng chỉ là một tên gọi class hay phương thức như bình thường thôi, chủ yếu là bạn hiểu được cách dùng của nó.

Abstract class được xem như là một lớp cha(base class) cho tất cả các lớp con(derived class) có cùng bản chất (kiểu, loại, nhiệm vụ của lớp).

Ví dụ: chúng ta có một lớp Animal gồm 2 phương thức:

Eat()
{
	// Thức ăn
	"Động vật ăn cỏ."
}

AnimalSound()
{
	// Tiếng kêu
	"Quạ Quạ."
}

– Và chúng ta có 3 lớp Cow, Cat, Bird kế thừa từ lớp Animal, tuy nhiên Cow, Cat, Bird thì:

・ Không cùng ăn một loại thức ăn.
・ Và tiếng kêu cũng không giống nhau.

– Do đó mà các phương thức Eat(), AnimalSound() cần phải khác nhau cho từng loại động vật, trong khi chúng cùng được kế thừa từ một lớp duy nhất là Animal.

Có thể bạn quan tâm: Tính kế thừa trong lập trình C#.

=> Để giải quyết vấn đề này, chúng ta cần đến abstract class, tức là lớp abstract Animal sẽ khai báo ra abstract method khuôn mẫu là Eat(), là AnimalSound(),… rồi ứng với mỗi lớp con kế thừa là Cow, Cat, Bird sẽ định nghĩa lại cho phù hợp với chất riêng của nó.

2. Cách khai báo lớp và phương thức trừu tượng
2. Cách khai báo lớp và phương thức trừu tượng

#1. Đối với lớp
– Cú pháp:

[<quyen_truy_cap>] abstract class <Ten_lop>
{
   ...
}

Trong đó: quyen_truy_cap : là public hay protected.

– Minh họa:

[code language=”csharp” highlight=”1″] public abstract class Animal
{

}
[/code]

#2. Đối với phương thức
– Cú pháp:

// Chỉ khai báo prototype
<quyen_truy_cap> abstract <kieu_tra_ve> <Ten_phuong_thuc>([<danh_sach_tham_so>]);

Trong đó:
quyen_truy_cap : là public hoặc protected.
danh_sach_tham_so : có thể có hoặc không.

– Minh họa:

[code language=”csharp” highlight=”2,3″] // abstract method
public abstract void Eat();
protected abstract void AnimalSound();
[/code]
3. Các đặc điểm của lớp và phương thức trừu tượng
3. Các đặc điểm của lớp và phương thức trừu tượng

abstract class không thể là một sealed class, vì sealed class không cho lớp khác kế thừa nó. Và không được khai báo với từ khóa static.

[code language=”csharp” highlight=”9,14″] // Khai báo đúng.
public abstract class Animal
{

}

// 2 khai báo bên dưới là sai.
// Error: ‘Animal’: an abstract class cannot be sealed or static
public abstract sealed class Animal
{

}

public static abstract class Animal
{

}
[/code]

abstract class cung cấp một phương thức giống nhau cho tất cả các lớp con. Phương thức khuôn mẫu để các lớp kế thừa nó tuân theo, được gọi là abstract method.

– Các lớp con kế thừa abstract class bắt buộc phải override các abstract method của lớp cha, tức là sẽ phải định nghĩa cho phương thức (ở lớp cha chỉ mới khai báo prototype).

abstract class phải chứa ít nhất một abstract method, nếu chúng ta khai báo abstract class mà không có abstract method nào thì chương trình cũng không có lỗi gì xảy ra, nhưng như vậy thì không đúng với tư tưởng của abstract class, khi đó thì chúng ta chỉ cần khai báo như một class thông thường không cần dùng từ khóa abstract.

– Trong một abstract class thì có thể có 3 loại phương thức: abstract method, virtual method, normal method.

[code language=”csharp” highlight=”4,7,13″] public abstract class Animal
{
// abstract method
protected abstract void AnimalSound();

// virtual method
public virtual void Eat()
{
Console.WriteLine( "Động vật ăn cỏ" );
}

// normal method
public void Run()
{
Console.WriteLine( "Chạy bằng 4 chân" );
}
}
[/code]

– Không thể tạo ra đối tượng (object instance) từ một abstract class, mà phải tạo thông qua một lớp con kế thừa từ nó.

abstract method chỉ được khai báo trong abstract class, vì chỉ khai báo prototype. Còn trong một class bình thường thì tất cả các phương thức không được khai báo prototype mà phải định nghĩa.

abstract method là phương thức chỉ được phép khai báo prototype (nguyên mẫu hàm), mà không có nội dung, không được định nghĩa. Và phải có phạm vi truy cập là public hoặc protected để lớp con có thể override, không được là private.
・ Phạm vi truy cập của abstract method phải giống nhau trong phần khai báo ở lớp cha lẫn lớp con. Nếu bạn đã khai báo phạm vi truy cập protected cho abstract method ở lớp cha thì trong lớp con bạn cũng phải sử dụng phạm vi truy cập protected khi override. Nếu phạm vi truy cập không giống nhau thì trình biên dịch sẽ báo lỗi.

abstract method không được khai báo sử dụng từ khóa virtual. Bởi vì bản thân abstract method đã bao hàm khái niệm virtual.

abstract method không thể là phương thức static.

[code language=”csharp” highlight=”8″] public abstract class Animal
{
// Khai báo đúng.
protected abstract void Eat();

// Khai báo sai.
// Error: A static member ‘Animal.AnimalSound()’ cannot be marked as override, virtual or abstract.
public static abstract void AnimalSound();
}
[/code]

4. Ví dụ minh họa cho đặc điểm của lớp và phương thức trừu tượng
4. Ví dụ minh họa cho đặc điểm của lớp và phương thức trừu tượng
[code language=”csharp”] using System;

namespace MinhHoangBlog
{
class Program
{
static void Main(string[] args)
{
// abstract class không thể tạo ra được đối tượng,
// mà phải thông qua lớp con kế thừa từ nó.
// SAI
//Animal animal = new Animal();
// Error: Cannot create an instance of the abstract class or interface ‘Animal’

// ĐÚNG
Animal cat = new Cat();

// hoặc:
Cat cat1 = new Cat();

Cow cow = new Cow();

// Gọi các phương thức
cat.Eat();
cow.Eat();

cat.AnimalSound();
cow.AnimalSound();

cat.Run();
cat.Run();

Console.ReadKey();
}
}

// Khai báo abstract class
public abstract class Animal
{
// abstract method
public abstract void AnimalSound();

// virtual method
public virtual void Eat()
{
Console.WriteLine( "Động vật ăn cỏ." );
}

// normal method
public void Run()
{
Console.WriteLine( "Chạy bằng 4 chân." );
}
}

// Lớp Cat kế thừa lớp Animal
public class Cat : Animal
{
// abstract method: bắt buộc lớp con phải override lại từ lớp cha.
// Khi override thì phạm vi truy cập phải giống của lớp cha: public
public override void AnimalSound()
{
Console.WriteLine( "Mèo meow meow." );
}

// virtual method: việc override thì không bắt buộc.
// Lớp con có thể dùng luôn định nghĩa từ lớp cha nếu phù hợp,
// hoặc override (định nghĩa lại) nếu không phù hợp.
// Khi override thì phạm vi truy cập phải giống của lớp cha: public
public override void Eat()
{
Console.WriteLine( "Mèo ăn cá." );
}

// normal method Run() thì dùng luôn của lớp cha không phải làm gì.
}

// Lớp Cow kế thừa lớp Animal
public class Cow : Animal
{
public override void AnimalSound()
{
Console.WriteLine( "Bò ummuu bò." );
}
}
}
[/code]

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

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

5. Sự khác nhau của abstract method và virtual method
5. Sự khác nhau của abstract method và virtual method
abstract method virtual method
Lớp con bắt buộc phải override abstract method ở lớp cha. Lớp con không bắt buộc phải override virtual method ở lớp cha. Nếu định nghĩa của virtual method ở lớp cha đã phù hợp với lớp con rồi thì có thể dùng luôn. Còn chưa phù hợp thì lớp con có quyền override virtual method ở lớp cha.
Tuyệt đối chỉ được khai báo là prototype ở lớp cha không có thân hàm, tức là chưa được định nghĩa. Cần phải được định nghĩa ở lớp cha.
Chỉ được sử dụng trong abstract class. Có thể sử dụng được trong cả abstract class và normal class.
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[...]

8 bình luận

Translate »