01/10/2018, 17:36

Abstract class vs interface

Một ngày nọ, mình đang ngồi thơ thẩn nghĩ về đâu đó, một người đồng nghiệp đến hỏi mình một câu rất đơn giản: “Khi nào mình nên dùng interface, khi nào mình nên dùng abstract ta?”. Thú thật, câu hỏi đó làm mình ngớ người ra và trả lời rất “ba láp”. Sau nhiều năm đi làm, ...

Một ngày nọ, mình đang ngồi thơ thẩn nghĩ về đâu đó, một người đồng nghiệp đến hỏi mình một câu rất đơn giản: “Khi nào mình nên dùng interface, khi nào mình nên dùng abstract ta?”.

Thú thật, câu hỏi đó làm mình ngớ người ra và trả lời rất “ba láp”. Sau nhiều năm đi làm, mình chỉ mải mê các công nghệ, framework, các công cụ mới trong lập trình nhưng không hề nhận ra là mấy thằng cha viết ra những thứ đó mới giỏi chứ mình sử dụng nó thôi thì giỏi cái gì. Và để viết ra được những thứ hay ho đấy thì những kiến thức nền tảng về OOP, design pattern, thuật toán mới là quan trọng nhất.

Hôm nay mạo muội dịch lại bài viết của tác giả Rahman Mahmoodi về sự khác nhau giữa abstract class và interface xem như là cách học lại các vấn đề cốt lõi trong lập trình.

1. Lớp dạng abstract là gì?

Lớp dạng abstract là một loại lớp đặc biệt mà chúng ta không thể khởi tạo được. Câu hỏi đặt ra là tại sao chúng ta cần một lớp không thể khởi tạo được vậy cà?

Vì lớp dạng abstract chỉ cho phép lớp khác thừa kế từ nó và không thể khởi tạo nó. Ưu điểm này là nó ép tạo ra hệ thống cây phân cấp cho tất cả các lớp con. Nói cách đơn giản, lớp abstract như là “giao kèo” mà bắt buộc tất cả các lớp con đi theo cùng tiêu chuẩn tương tự nhau.

2. Interface là gì?

Interface không phải là lớp. Đó là một thực thể được định nghĩa bởi từ khóa interface. Interface không có người thực hiện; nó chỉ có dấu hiệu hay nói cách khác, chỉ định nghĩa những phương thức rỗng. Interface có một điểm tương đông với lớp dạng Abstract, nó là một “giao kèo” được sử dụng để xác định phân cấp cho tất cả các lớp con hoặc nó định nghĩa tập các phương thức và các đối số của nó. Sự khác biệt chính giữa chúng là một lớp có thể thực hiện nhiều hơn một interface nhưng chỉ có thể kế thừa từ MỘT lớp dạng abstract. Vì C # không hỗ trợ đa kế thừa, giao diện được sử dụng để thực hiện đa kế thừa.

3. So sánh interface và lớp dạng abstract
Khi chúng ta tạo ra một interface, chúng ta về cơ bản tạo ra một tập các phương thức rỗng và những phương thức rỗng này sẽ được “đong đầy” bởi những lớp nào thực thi interface (và người đong đầy là chúng ta – lập trình viên). Ưu điểm là nó giúp cho một lớp trở thành một phần của hai lớp: một là từ thừa kế và một là từ interface.

Khi chúng ta tạo một lớp trừu tượng, chúng ta đang tạo ra một lớp cơ sở có thể có một hoặc nhiều phương thức hoàn chỉnh nhưng ít nhất một hoặc nhiều phương thức còn lại dở dang và khai báo abstract. Nếu tất cả các phương thức của một lớp dạng abstract là dở dang thì nó là giống như một interface thôi. Mục đích của một lớp trừu tượng là cung cấp định nghĩa cơ sở cho các lớp dẫn xuất (lớp con của nó) sẽ làm việc và sau đó cho phép các lập trình viên viết code cho việc thực thi các phương thức.

Có một số điểm tương đồng và khác biệt giữa interface và lớp dạng abstract mà tôi đã sắp xếp trong một bảng để dễ dàng so sánh:

# Tính năng Interface Lớp dạng Abstract
1 Đa thừa kế Một lớp có thể thừa kế nhiều interface. Một lớp chỉ thừa kế một lớp dạng trừu tượng.
2 Việc thực thi mặc định Interface không thể cung cấp bất kì code, nó chỉ là những dấu hiệu Lớp dạng abstract có thể cung cấp code hoàn chỉnh hoặc chỉ cung cấp những chi tiết phải bị ghi đè bởi lớp con
3 Access Modfiers Interface không có access modifiers cho phương thức, thuộc tính, Mọi thứ được giả định là public Lớp dạng abstract có thể chứa access modifier cho phương thức, thuộc tính…
4 Core VS Peripheral Interface dùng để định nghĩa những khả năng bên ngoài của một lớp. Ví dụ như lớp Human và lớp Vehicle có thể thực thi IMovable interface. Lớp dạng abstract định nghĩa cốt lõi của một lớp và sử dụng cho những object cùng kiểu.
5 Homogeneity Nếu những việc thực thi khác nhau chỉ chia sẻ những “dấu hiệu” của phương thức, khi đó chúng ta nên sử dụng interface Nếu những việc thực thi khác nhau cùng loại và có những thứ chung như status, behavior, khi đó chúng ta nên sử dụng lớp dạng abstract.
6 Speed Cần nhiều thời gian để tìm phương thức thực tế tương ứng với lớp. Nhanh
7 Adding functionality (Versioning) Nếu chúng ta thêm một phương thức mới vào interface khi đó chúng ta phải lùng sục hết tất cả các lớp nào đang thực thi interface và định nghĩa thực thi cho phương thức mới. Nếu chúng ta thêm phương thúc mới vào lớp dạng abstract chúng ta có thể lựa chọn cung cấp những thực thi mặc định và do đó tất cả các code đang tồn tại vẫn chạy bình thường.
8 Fields and Constants Không thể định nghĩa trong interface Lớp dạng abstract có thể định nghĩa

Bài viết gốc


0