Trang chủ » Interface và Abstract Class trong lập trình hướng đối tượng
Lập trình hướng đối tượng

Interface và Abstract Class trong lập trình hướng đối tượng

Ngày trước khi mình còn học môn Lập trình hướng đối tượng của thầy Nguyễn Minh Huy (bạn nào học KHTN TPHCM chắc biết thầy), lớp có 1 buổi thuyết trình so sánh OOP của 2 ngôn ngữ C++ và Java. Mọi chuyện có lẽ suôn sẻ đến khi thầy trợ giảng hỏi về sự khác biệt của Interface và Abstract Class trong Java. Thật sự mình cũng hơi đớ người vì chả biết trả lời sao, và cảm thấy hơi “bối rối”. Khuyên nhủ bản thân về thì search thử mà rốt cuộc lại quên béng đi, đến bây giờ mới chợt nhớ đến 2 thằng này…

Xin chào mọi người! Chắc khi học về Lập trình hướng đối tượng thì ai ai cũng tiếp xúc qua về Interface và Abstract Class (nếu ai học về C++ thì sẽ là Pure Virtual Class và Virtual Class). Vậy đã bao giờ bạn tự thắc mắc rằng tại sao lại sinh ra 2 thằng này để bao developer khổ sở, bao sinh viên đau đầu mỗi kì thi chưa? Ở đây mình sẽ sử dụng ngôn ngữ C# để so sánh. Trước hết thì ta cùng tìm hiểu 1 chút về khái niệm 2 thằng này đã.

Interface là gì?

interface
Interface là gì?

Đầu tiên ta cần phải lưu ý, Interface KHÔNG PHẢI là Class. Nó giống như 1 cái vỏ rỗng, chỉ có thể khai báo các methods và constants, có thể xem nó như 1 pattern vậy. Các members trong Interface đều mặc định là public. Và 1 class có thể implement NHIỀU interface

// Giả định mọi phương tiện đều có những chức năng được liệt kê trong Interface
public interface PhuongTien
{
    public void Chay();
    public int KiemTraNhienLieu();
}

// Một công ty quyết định sản xuất xe hơi dựa trên bản thảo và những kiến thức thông thường về xe
public class XeHoi implements PhuongTien
{
    private int NhienLieu;
    public override void Chay()
    {
        Console.WriteLine("Len nao anh em oi!");
    }
    public override int KiemTraNhienLieu()
    {
        return this.NhienLieu;
    }
}

Như ta đã thấy, 1 chiếc xe hơi được làm ra thì phải dựa trên những kiến thức thông thường về xe (xe có 4 bánh, máy lạnh, có vô lăng, số lùi,…). Ta không thể nào thiết kế 1 chiếc xe hơi chỉ có 2 bánh, hay là làm cho cái vô lăng thành tay lái xe máy. Interface cũng như vậy, khi thiết kế 1 interface thì lập trình viên sẽ nghĩ “à tôi sẽ lập trình thứ này theo những nguyên tắc A, B, C,… mà tôi đề ra” và những thằng kế thừa interface sẽ nghĩ “à tôi sẽ viết lớp này dựa theo những nguyên tắc A, B, C,… mà ông thần trên đề ra”.

Abstract Class là gì?

Những bạn chưa quen về Abstract Class có thể nhầm lẫn giữa 2 thằng này. Đầu tiên thì Abstract Class (có thể gọi là ABC) là 1 class (nghe nó hại não quá :v). Khác với Interface, nó có thể khai báo và định nghĩa các methods, members khác, và nó cũng có thể sử dụng các kiểu privateprotectedpublic (không như Interface chỉ sử dụng mỗi thằng public). Tuy nhiên, 1 class chỉ có thể extends duy nhất một abstract class (điều này giúp hạn chế Diamond Problem thường gặp nhất ở C++)

diamond problem
Diamond Problem thường thấy ở C++ khi 1 class có thể kế thừa nhiều class, và các class đó đều kế thừa từ 1 base class.
// Giả định mọi phương tiện chạy xăng đều có những chức năng được liệt kê trong Abstract Class
public abstract class PhuongTien
{
    private int NhienLieu;
    // Xe nào cũng cần nhiên liệu để chạy, vậy thì tại sao ta phải bắt override lại?
    public int KiemTraNhienLieu()
    {
        return this.NhienLieu;
    }
    // Tuy nhiên mỗi phương tiện có 1 cách chạy riêng
    // Ta cần phải chỉ rõ từng phương tiện chạy như thế nào
    public abstract void Chay();
}

// Một công ty quyết định sản xuất xe hơi dựa trên bản thảo và những kiến thức thông thường về xe
public class XeHoi extends PhuongTien
{
    public override void Chay()
    {
        Console.WriteLine("Len nao anh em oi!");
    }
}

Abstract Class nhìn có vẻ khá giống Interface 1 vài chỗ. Ta cứ tưởng tượng “phương tiện di chuyển thì đã có những cái chung giống nhau, việc ta cần làm là thiết kế ra những cái riêng biệt của từng phương tiện”.

Vậy phân biệt nó bằng cách nào?

Khi ta tạo 1 Interface, có nghĩa là ta đang ép các class implement nó phải override toàn bộ các methods trong Interface đó. Tuy nhiên với Abstract Class thì đơn giản là ta chỉ override các methods còn thiếu, các methods đã được định nghĩa sẵn trong Abstract Class sẽ được class con sử dụng bình thường, giảm thiểu việc phải override lặp đi lặp lại nhiều lần. Nếu 1 Abstract Class mà toàn bộ các methods đều là abstract thì nó sẽ tương đương với 1 Interface.

Tuỳ các ngôn ngữ lập trình mà 2 thằng này có những khái niệm khác nhau. Với C++ thì là Pure Virtual Class và Virtual Class (hàm thuần ảo và hàm ảo). Với C#, Java thì 2 thằng phân biệt rạch ròi. Tuy nhiên ở PHP thì Interface là 1 Abstract Class không có định nghĩa các methods.

Tại sao??? Tại sao lại phải đẻ thêm 2 thằng này để bao dev khốn khổ???
Tại sao??? Tại sao lại phải đẻ thêm 2 thằng này để bao dev khốn khổ???

Dù vậy, lý thuyết vẫn là lý thuyết. Chúng ta cần linh động trong việc sử dụng Interface hay Abstract Class, bởi vì viết 1 phần mềm là công việc của chúng ta, chứ không phải của các dòng code vô tri.

Trên đây là bài viết về Interface và Abstract Class trong lập trình hướng đối tượng. Cảm ơn các bạn đã chú ý theo dõi. Hẹn gặp lại ở những bài viết tiếp theo!

About the author

Võ Hoài Sơn

Tính tình bất định
Chọc vào là bịnh
Rất yêu lập trình
Luôn code hết mình
Mình hiện đang là sinh viên của trường ĐH Khoa học tự nhiên TPHCM. Bản thân rất thích code, kiêm luôn cả mần thơ nên thường hơi hâm hâm dở dở. Ngoài ra chém gió, chém chuối, chém trái cây các kiểu cũng là sở trường của mình. Rất mong được làm quen với các bạn :D

Add Comment