[DOTNETVN] Phân biệt Abstract Class và Interface

Trong bài viết này mình sẽ trình bày ngắn gọn về Abstract và Interface, cách dùng cũng như nên dùng trong trường hợp nào.

Abstract Class vs Interface

1. Abstract Class là gì ?

Abstract Class hay còn gọi là lớp trừu tượng, vậy trừu tượng là gì ? ...thì là thứ mà bạn biết về nó nhưng không thể định nghĩa nó một cách tường minh được ví vụ như khi nói tới động vật bạn hiểu gì ? bạn có định nghĩa được động vật không câu trả lời là không nhưng bạn biết nếu là động vật sẽ đi được, ăn được, có hình dáng, màu sắc...

Abstract Classmột thiết kế dùng cho các lớp có cùng bản chất hay những đặc điểm chung, xét sơ đồ bên dưới

Khi nhìn vào sơ đồ các bạn sẽ thấy ta có 1 lớp Abstract tên là Animal có các phương thức Move(), Eat() (ngoài ra còn có các thuộc tính nữa nhưng ở đây mình chỉ liệt kê Method cho ngắn cheeky) nhưng các phương thức này ở lớp Animal sẽ không được định nghĩa vì bản chất chúng ta không biết Animal sẽ Move()Eat() như thế nào đúng không. Tiếp theo mình tạo 3 lớp con kế thừa từ lớp AnimalFish, CatSnake, lúc này bạn sẽ định nghĩa lại các hàm MoveEat cho từng đối tượng vì bạn có thể biết chính xác được cá, mèo và rắn di chuyển thế nào, ăn thế nào, mình sẽ minh họa bằng cách cài đặt code cho sơ đồ này.

public abstract class Animal
{
    abstract public void Move();
    
    abstract public void Eat();
}

public class Fish
{
    public Fnish()
    {
        Console.WriteLine("This is fish");
    }
    
    public override void Move()
    {
        Console.WriteLine("Fish is moving");
    }
    public override void Eat()
    {
        Console.WriteLine("Fish is eating");
    }
}

public class Cat
{
    public Cat()
    {
        Console.WriteLine("This is cat");
    }
    
    public override void Move()
    {
        Console.WriteLine("Cat is moving");
    }
    public override void Eat()
    {
        Console.WriteLine("Cat is eating");
    }
}

public class Snake
{
    public Snake()
    {
        Console.WriteLine("This is snake");
    }
    
    public override void Move()
    {
        Console.WriteLine("Snake is moving");
    }
    public override void Eat()
    {
        Console.WriteLine("Snake is eating");
    }
}

//Main Method
static void Main()
{
    Animal animal = new Fish();
    animal.Move();
    animal.Eat();
    
    animal = new Cat();
    animal.Move();
    animal.Eat();
    
    animal = new Snake();
    animal.Move();
    animal.Eat();
}

Ghi chú: Khi sử dụng abstract bạn cần sử dụng từ khóa override để định nghĩa lại phương thức ở lớp con, và khi bạn thêm một phương thức mới vào lớp abstract thì các lớp con có thể định nghĩa lại phương thức này hoặc không, nó hoàn toàn không phá vỡ kiến trúc, một lớp chỉ có thể kế thừa 1 abstract class

2. Interface là gì ?

Interface là đa hình nó quan tâm đến hành vi của các đối tượng, không như abstract quan tâm đến bản chất, các điểm chung của đối tượng. Nói thế này cho dễ hiểu, mình có 2 lớp là CatMoon, cả CatMoon đều có chung 1 phương thức là di chuyển nhưng xét về bản chất thì CatMoon (con mèo và mặt trăng) chả có gì dính dáng nhau cả đúng không :), các bạn xem qua sơ đồ bên dưới

Trên sơ đồ mình có một interface IObjectMove, chứa các phương thức liên quan đến sự di chuyển của một đối tượng ở đây có 2 phương thức là MoveRun. Lớp CatMoon sẽ kế thừa interface này và định nghĩa lại 2 phương thức trên, mình sẽ minh họa sơ đồ trên bằng code

public interface IObjectMove
{
    void Move();
    void Run();
}

public class Cat:IObjectMove
{
    public Cat()
    {
        Console.WriteLine("This is Cat");
    }
    
    public void Move()
    {
        Console.WriteLine("Cat is moving");
    }
    
    public void Run()
    {
        Console.WriteLine("Cat is running");
    }
}

public class Moon:IObjectMove
{
    public Moon()
    {
        Console.WriteLine("This is our moon");
    }
    
    public void Move()
    {
        Console.WriteLine("Moon is moving");
    }
    
    public void Run()
    {
        Console.WriteLine("Moon is moving very fast");
    }
}

//Main Method
static void Main()
{
    IObjectMove objectMove = new Cat();
    objectMove.Move();
    objectMove.Run();
    
    objectMove = new Moon();
    objectMove.Move();
    objectMove.Run();
}

Ghi Chú: Đối với interface bạn không cần dùng từ khóa override, nhưng điểm khác biệt so với abstract là nếu bạn thêm một phương thức vào interface nó sẽ phá vỡ kiến trúc vì thế nên bạn buộc phải định nghĩa phương thức này ở lớp con nếu không chương trình sẽ báo lỗi, một lớp có thể kế thừa nhiều interface.

Vậy người ta thường dùng khi nào? khi thiết kế Architect (kiến trúc) cho hệ thống hoặc sử dụng trong design pattern để code bạn dễ bảo trì cũng như dễ dàng nâng cấp, mở rộng sau này, các bạn có thể tham khảo về design pattern bằng cách bấm => đây