Interface là gì?
Trong lập trình hướng đối tượng, interface
là một tập hợp các phương thức (và thuộc tính) mà một class phải triển khai. Interface không chứa phần triển khai cụ thể, mà chỉ định nghĩa cấu trúc
mà các lớp phải tuân theo. Điều này giúp các lớp khác nhau có thể đảm bảo tính nhất quán và dễ mở rộng hệ thống.
Trong Dart, mọi class đều có thể được sử dụng như một interface. Điều này có thể khá lạ lẫm lúc đầu, nhưng bạn sẽ nhanh chóng quen với nó. Tuy nhiên, để thực hành tốt hơn, chúng ta nên sử dụng các class trừu tượng (abstract class) để tạo interface. Hãy cùng tìm hiểu cách sử dụng và áp dụng interface trong Dart qua bài viết này.
1. Tạo Interface bằng Abstract Class
Trong Dart, bạn có thể sử dụng abstract class để định nghĩa một interface. Ví dụ:
abstract class MyInterface { void method(); int get getter;
} class Example implements MyInterface { void method() { } int get getter => 10;
}
Trong ví dụ trên, class Example
sử dụng từ khóa implements
để thực hiện (implement) interface MyInterface
. Từ khóa implements
buộc chúng ta phải ghi đè (override
) tất cả các phương thức của MyInterface
, bao gồm cả phương thức trừu tượng và không trừu tượng.
Điểm khác biệt giữa implements
và extends
là khi sử dụng implements
, bạn phải ghi đè tất cả các các phương thức và thuộc tính của interface
, trong khi extends
không bắt buộc phải làm như vậy.
2.Tại sao nên sử dụng Abstract Class để tạo Interface?
Bạn có thể sử dụng class thông thường để tạo interface
, nhưng điều này không được khuyến khích. Ví dụ:
class MyInterface { void method() {} int get getter => 0;
} class Example implements MyInterface { void method() { } int get getter => 10;
}
Trong ví dụ này, MyInterface
là một class thông thường nên các thành viên của nó cần phải có phần thân. Điều này đi ngược lại với bản chất của một interface, vì interface chỉ nên định nghĩa cấu trúc của phương thức mà không cần quan tâm đến cách thức triển khai. Vì vậy, để đảm bảo rằng interface không được khởi tạo và chỉ đóng vai trò định nghĩa cấu trúc, chúng ta nên sử dụng abstract class thay vì class thông thường.
3. Sử dụng extends và implements trong Dart
extends
Sử dụng từ khóa extends khi bạn muốn một class con kế thừa các thành viên từ class cha. Bạn có thể ghi đè lại các phương thức nếu cần, nhưng không bắt buộc phải ghi đè tất cả. Ví dụ:
abstract class FileReader { final File file; const FileReader(this.file); String get path => file.path; bool get isPathAbsolute => file.isAbsolute; String readContents();
} class TextReader extends FileReader { const TextReader(super.file); String readContents() => 'contents of a .txt file';
}
Trong ví dụ này, TextReader
kế thừa từ FileReader
và chỉ cần triển khai phương thức readContents()
. Các thuộc tính khác như path và isPathAbsolute
đã được kế thừa từ class cha, giúp tránh việc lặp lại mã nguồn.
implements
Sử dụng từ khóa implements
khi bạn muốn định nghĩa một cấu trúc mà không chia sẻ bất kỳ triển khai nào. Ví dụ:
abstract class Sorter { void sort(); String get name;
} class MergeSort implements Sorter { void sort() { } String get name => 'Merge sort';
} class QuickSort implements Sorter { void sort() { } String get name => 'Quick sort';
}
Ở đây, chúng ta định nghĩa các thuật toán sắp xếp khác nhau như MergeSort
và QuickSort
, cả hai đều triển khai interface Sorter
. Mỗi thuật toán đều có logic riêng, và implements
đảm bảo rằng mọi thuật toán đều có cùng cấu trúc (một phương thức và một getter).
4. Khi nào nên sử dụng extends và implements?
extends:
Sử dụng khi bạn muốn chia sẻ các hành vi chung dọc theo một hệ thống phân cấp. Nếu bạn có một số hành vi chung cần được áp dụng cho tất cả các lớp con, hãy sử dụng extends để tận dụng tính kế thừa.
implements:
Sử dụng khi bạn chỉ cần định nghĩa cấu trúc của một lớp mà không cần chia sẻ mã triển khai. Điều này phù hợp với việc tạo các interface để đảm bảo rằng tất cả các lớp triển khai đều tuân theo một cấu trúc nhất định mà không cần dùng lại mã nguồn.
Kết luận
Trong Dart, bạn có nhiều lựa chọn để định nghĩa và sử dụng interface. Bạn có thể sử dụng abstract class với từ khóa implements
để đảm bảo rằng mọi thành viên đều được triển khai, hoặc sử dụng extends
để tận dụng tính kế thừa. Hãy luôn nhớ rằng abstract class phù hợp để chia sẻ hành vi, trong khi interface được sử dụng để định nghĩa cấu trúc mà không có triển khai cụ thể.
Hy vọng bài viết này đã giúp bạn hiểu rõ hơn về cách sử dụng interface trong Dart. Hãy thử áp dụng vào các dự án của bạn để tạo ra mã nguồn rõ ràng và dễ bảo trì hơn!