Interface trong Java là một cách để đạt tính trừu tượng, nó tương tự với lớp (Class) của Java. Tuy nhiên, nó có nhiều điểm khác biệt so với Class .Trong bài viết này, chúng ta sẽ tìm hiểu về các Interface. Chúng ta sẽ tìm hiểu cách triển khai các interface và thời điểm sử dụng chúng một cách chi tiết cùng với sự các ví dụ dẫn chứng.
Interface trong Java
Interface là một lớp trừu tượng hoàn toàn bao gồm một nhóm các phương thức không có phần thân hay nội dung bên trong nó. Trong Java, một Interface xác định một tập hợp các đặc tả mà các lớp khác phải thực hiện triển khai, do đó, các lớp sẽ kế thừa các phương thức trừu tượng của Interface.
Ví dụ:
1 2 3 |
Interface sinh_vien { public void in_thong_tin(); } |
Ở đây, chúng ta đã sử dụng từ khóa Interface để tạo một Interface có tên là sinh_vien. Interface sinh_vien định nghĩa một đặc tả in_thong_tin(). Bây giờ, các lớp sử dụng Interface này phải triển khai cho phương thức in_thong_tin().
Ví dụ:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
interface sinh_vien { void in_thong_tin(); } class sinh_vien_y implements sinh_vien { public void in_thong_tin() { System.out.println("Toi la sinh vien y"); } } class Main { public static void main(String[] args) { sinh_vien_y sv = new sinh_vien_y(); sv.in_thong_tin(); } } |
Kết quả:
1 |
Toi la sinh vien y |
Trong ví dụ trên, chúng ta đã tạo một interface có tên là sinh_vien. Interface bao gồm một phương thức trừu tượng in_thong_tin(). Ở đây, lớp sinh_vien_y sẽ phải triển khai Interface và cung cấp việc triển khai cho phương thức trong Interface đó.
Không bắt buộc phải sử dụng từ khóa abstract trong khi khai báo các phương thức trừu tượng bên trong Interface bởi một Interface chỉ bao gồm các phương thức trừu tượng, không chứa các phương thức thông thường.
Chú ý: Tất cả các phương thức bên trong Interface mặc định đều là public và tất cả các trường đều mặc định là public static final.
Ví dụ:
1 2 3 4 5 6 |
interface giao_dien { //mặc định là public static final String a = "Xin chao"; // mặc định là public void in_thong_tin(); } |
Triển khai cho một Interface
Giống như các lớp trừu tượng, chúng ta không thể tạo các đối tượng của một Interface. Tuy nhiên, chúng ta có thể triển khai một Interface. Chúng ta sẽ sử dụng từ khóa implements để triển khai một Interface.
Ví dụ:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
interface sinh_vien { void in_thong_tin(int a, int b); } class sinh_vien_y implements sinh_vien { public void in_thong_tin(int a, int b) { System.out.println(a + " " + b); } } class Main { public static void main(String[] args) { sinh_vien_y sv = new sinh_vien_y(); sv.in_thong_tin(124, 43); } } |
Kết quả:
1 |
124 43 |
Trong ví dụ trên, chúng ta đã tạo một Interface có tên là sinh_vien. Interface chứa một phương thức trừu tượng in_thong_tin(). Ở đây, lớp sinh_vien_y sẽ triển khai cho lớp sinh_vien và cho phương thức in_thong_tin().
Chú ý: Một lớp có thể triển khai nhiều Interface.
Ví dụ:
1 2 3 4 5 6 7 8 9 10 11 |
interface sinh_vien { //Đoạn mã } interface sinh_vien2 { // Đoạn mã } class sinh_vien3 implements sinh_vien2, sinh_vien { //Đoạn mã } |
Thừa kế Interface
Tương tự như các lớp, Interface có thể được thừa kế từ các Interface khác. Từ khóa extends được sử dụng để kế thừa Interface.
Ví dụ:
1 2 3 4 5 6 7 |
interface sinh_vien { //Đoạn mã } interface sinh_vien_y extends sinh_vien { //Đoạn mã } |
Ở đây, Interface sinh_vien_y kế thừa Interface sinh_vien. Bây giờ, nếu bất kỳ lớp nào triển khai sinh_vien_y, nó sẽ phải cung cấp các triển khai cho tất cả các phương thức trừu tượng của cả sinh_vien_y và sinh_vien.
Chú ý: Một Interface có thể kế thừa nhiều Interface khác.
Ví dụ:
1 2 3 4 5 6 7 8 9 10 11 |
interface sinh_vien { //Đoạn mã } interface sinh_vien2 { //Đoạn mã } interface sinh_vien3 extends sinh_vien2, sinh_vien { //Đoạn mã } |
Ưu điểm của Interface trong Java
1. Các Interface cung cấp các thông số kỹ thuật mà một lớp phải tuân theo.
Trong ví dụ trước, chúng ta đã sử dụng in_thong_tin () như một đặc tả bên trong interface sinh_vien. Điều này giống như thiết lập một quy tắc rằng sẽ phải in ra các thông tin của từng sinh viên của mỗi trường khác nhau.
2. Tương tự như các lớp trừu tượng, các Interface giúp chúng ta đạt được sự trừu tượng trong Java.
Ở đây, chúng ta biết in_thong_tin () sẽ in ra thông tin của sinh viên nhưng thông tin của mỗi sinh viên của các trường là khác nhau. Do đó, việc triển khai in_thong_tin() là độc lập với nhau.
3. Các Interface cũng được sử dụng để đạt được tính đa kế thừa trong Java.
Ví dụ:
1 2 3 4 5 6 7 8 9 10 11 |
interface sinh_vien { //Đoạn mã } interface sinh_vien2 { //Đoạn mã } interface sinh_vien3 implements sinh_vien2, sinh_vien { //Đoạn mã } |
Ở đây, lớp sinh_vien3 sẽ triển khai hai interface khác nhau. Đây là cách mà chúng ta đạt được tính đa kế thừa trong Java.
Các phương thức mặc định trong Interface
Với Java 8, bây giờ chúng ta có thể thêm các phương thức với việc triển khai bên trong một Interface. Các phương thức này được gọi là phương thức mặc định.
Để khai báo các phương thức mặc định bên trong các Interface, chúng ta sử dụng từ khóa default.
Ví dụ:
1 2 3 |
public default void abc () { // Đoạn mã của abc () } |
Tại sao cần các phương thức mặc định?
Giả sử, chúng ta cần thêm một phương thức mới trong một Interface. Chúng ta có thể thêm phương thức vào Interface của mình một cách dễ dàng mà không cần triền khai. Tất cả các lớp triển khai Interface đó phải triển khai cho phương thức. Nếu một số lượng lớn các lớp đang triển khai Interface này, chúng ta cần theo dõi tất cả các lớp này và thực hiện các thay đổi bên trong. Điều này sẽ không chỉ nhàm chán mà còn rất dễ xảy ra lỗi.
Để giải quyết điều này, Java đã đưa ra các phương thức mặc định. Các phương thức mặc định được kế thừa giống như các phương thức thông thường.
Ví dụ:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
interface sinh_vien { void in_thong_tin(); default void lay_thong_tin() { System.out.println("Thong tin can lay!"); } } class sinh_vien_y implements sinh_vien { public void in_thong_tin() { int ID_sv = 6; System.out.println("ID cua sinh vien y la: " + ID_sv); } public void lay_thong_tin() { System.out.println("Thong tin can lay cua sinh vien y!"); } } class sinh_vien_luat implements sinh_vien { public void in_thong_tin() { int ID_sv = 12; System.out.println("ID cua sinh vien luat la: " + ID_sv); } } class Main { public static void main(String[] args) { sinh_vien_y sv = new sinh_vien_y(); sv.in_thong_tin(); sv.lay_thong_tin(); sinh_vien_luat sv1 = new sinh_vien_luat(); sv1.in_thong_tin(); sv1.lay_thong_tin(); } } |
Kết quả:
1 2 3 4 |
ID cua sinh vien y la: 6 Thong tin can lay cua sinh vien y! ID cua sinh vien luat la: 12 Thong tin can lay! |
Trong ví dụ trên, chúng ta đã tạo một Interface có tên sinh_vien. Nó có một phương thức mặc định lay_thong_tin() và một phương thức trừu tượng in_thong_tin(). Ở đây, chúng ta đã tạo ra hai lớp sinh_vien_y và Sinh_vien_luat triển khai cho sinh_vien. Lớp sinh_vien_y cung cấp việc triển khai phương thức in_thong_tin() và ghi đè phương thức lay_thong_tin(). Tuy nhiên, lớp sinh_vien_luat chỉ cung cấp việc triển khai cho phương thức in_thong_tin() của Interface.
Khi thực hiện việc gọi phương thức lay_thong_tin() bằng đối tượng sinh_vien_y, phương thức ghi đè sẽ được gọi. Tuy nhiên, trong trường hợp của đối tượng sinh_vien_luat, phương thức mặc định sẽ được gọi.
Phương thức private và static trong Interface
Java 8 cũng đã thêm một tính năng khác để bao gồm các phương thức tĩnh bên trong một Interface. Tương tự như một lớp, chúng ta có thể truy cập các phương thức tĩnh của một Interface bằng cách sử dụng các tham chiếu của nó.
Ví dụ:
1 2 3 4 |
interface sinh_vien { Phuong_thuc_tinh(){..} } sinh_vien.Phuong_thuc_tinh(); |
Chú ý: Với việc Java 9, các phương thức private cũng được hỗ trợ trong các Interface. Chúng ta không thể tạo các đối tượng của một Interface. Do đó, các phương thức private được sử dụng như các phương thức trợ giúp nhằm hỗ trợ cho các phương thức khác trong Interface.
Ví dụ:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
interface sinh_vien { void in_thong_tin(); default void lay_thong_tin(){ System.out.println("Thong tin da duoc lay!"); } } class sinh_vien_y implements sinh_vien { private int ID_sv; sinh_vien_y(int a) { this.ID_sv = a; } public void in_thong_tin() { System.out.println(ID_sv); } } class Main { public static void main(String[] args) { sinh_vien_y sv = new sinh_vien_y(27); sv.in_thong_tin(); sv.lay_thong_tin(); } } |
Kết quả:
1 2 |
27 Thong tin da duoc lay! |
Trong chương trình trên, chúng ta đã tạo một Interface có tên là sinh_vien. Nó bao gồm một phương thức mặc định lay_thong_tin() và một phương thức trừu tượng in_thong_tin().
Chúng ta có thể lay_thong_tin() của tất cả các sinh viên theo cùng một cách nên chúng ta đã triển khai đoạn mã bên trong của lay_thong_tin() trong Interface sinh_vien. Bây giờ, tất cả các sinh viên của các trường sẽ triển khai cho Interface sinh_vien có thể sử dụng lay_thong_tin(). Tuy nhiên, thông tin sinh viên của mỗi trường là khác nhau. Do đó, in_thong_tin() được chứa trong Interface sinh_vien mà không cần thực hiện triển khai. Bất kỳ lớp sinh viên của trường nào mà triển khai cho Interface sinh_vien sẽ phải triển khai cho phương thức in_thong_tin() để in ra các thông tin khác nhau.
Trên đây là khái niệm và ví dụ cơ bản về Interface trong Java. Hy vọng mọi người có thể áp dụng vào trong chương trình của mình. Mọi người hãy tiếp tục theo dõi các bài tiếp theo và cập nhật các bài mới nhất trên tek4 nhé!
P/s: Cảm ơn mọi người!