Phương thức mặc định và tĩnh trong giao diện
Thuộc phần Lập trình hướng đối tượng trong hành trình Java của Coddy. Bài học 37 trên 87.
Ban đầu, interface chỉ có thể chứa các phương thức trừu tượng không có phần triển khai. Từ Java 8, interface có thêm khả năng chứa phương thức mặc định và phương thức tĩnh, nhờ đó linh hoạt hơn.
Phương thức mặc định cung cấp cách triển khai ngay trong giao diện bằng từ khóa default. Các lớp triển khai giao diện sẽ tự động kế thừa hành vi này nhưng có thể ghi đè nếu cần:
public interface Drawable {
void draw();
default void display() {
System.out.println("Displaying on screen...");
draw();
}
}Mọi lớp triển khai Drawable đều có sẵn phương thức display(). Điều này đặc biệt hữu ích khi thêm phương thức mới vào các giao diện hiện có mà không làm hỏng các lớp đã triển khai chúng.
Phương thức tĩnh trong interface hoạt động giống như phương thức tĩnh trong lớp. Chúng thuộc về chính interface và được gọi bằng tên interface:
public interface MathOperations {
static int add(int a, int b) {
return a + b;
}
}
// Cách sử dụng
int result = MathOperations.add(5, 3);Các phương thức giao diện tĩnh không thể bị ghi đè và không được các lớp triển khai kế thừa. Chúng hữu ích cho các phương thức tiện ích liên quan đến mục đích của giao diện.
Nếu một lớp triển khai hai giao diện có cùng chữ ký phương thức mặc định, lớp đó phải ghi đè phương thức ấy để giải quyết xung đột.
Thử thách
DễHãy xây dựng một hệ thống nhắn tin minh họa cả phương thức mặc định lẫn phương thức tĩnh trong giao diện (interface). Bạn sẽ tạo một giao diện có sẵn chức năng để các lớp triển khai có thể dùng trực tiếp hoặc tùy chỉnh khi cần.
Bạn sẽ sắp xếp code trong bốn tệp:
Messenger.java: Định nghĩa một giao diện đại diện cho bất kỳ dịch vụ nhắn tin nào. Giao diện này cần khai báo một phương thức trừu tượngsendMessage(String message)trả về void. Thêm một phương thức mặc định tên làsendWithTimestamp(String message), in ra:[TIMESTAMP]rồi gọisendMessage(message). Đồng thời thêm một phương thức tĩnh tên làformatMessage(String message), trả về thông điệp đã chuyển thành chữ in hoa.EmailMessenger.java: Tạo một lớp triển khaiMessenger. Lớp này có trườngrecipient(String). Thêm hàm khởi tạo để khởi tạo người nhận. Triển khaisendMessage()để in ra:Email to [recipient]: [message]. Lớp này dùng nguyên trạng phương thức mặc địnhsendWithTimestamp().SMSMessenger.java: Tạo một lớp khác triển khaiMessenger. Lớp này có trườngphoneNumber(String). Thêm hàm khởi tạo để khởi tạo số điện thoại. Triển khaisendMessage()để in ra:SMS to [phoneNumber]: [message]. Ghi đè phương thức mặc địnhsendWithTimestamp()để in ra:[URGENT]rồi gọisendMessage(message), thay vì dùng cách xử lý dấu thời gian mặc định.Main.java: Kết hợp mọi thứ để minh họa cả phương thức mặc định lẫn phương thức tĩnh của giao diện. Bạn sẽ nhận ba đầu vào: người nhận email, số điện thoại và thông điệp. Trước tiên, dùng phương thức tĩnhMessenger.formatMessage()để định dạng thông điệp và lưu lại. Sau đó, tạo một EmailMessenger và một SMSMessenger. Với mỗi trình nhắn tin, gọisendWithTimestamp()bằng thông điệp đã định dạng: hãy để ý EmailMessenger dùng cách triển khai mặc định, còn SMSMessenger dùng phiên bản đã ghi đè.
Bạn sẽ nhận ba đầu vào: người nhận email (String), số điện thoại (String) và thông điệp (String).
Đầu ra cần có tổng cộng bốn dòng, hai dòng cho mỗi trình nhắn tin: một dòng tiền tố ([TIMESTAMP] hoặc [URGENT]), theo sau là dòng thông điệp. EmailMessenger sẽ hiển thị tiền tố dấu thời gian mặc định, còn SMSMessenger sẽ hiển thị tiền tố khẩn cấp tùy chỉnh. Cả hai đều dùng thông điệp đã được định dạng thành chữ in hoa bằng phương thức tĩnh!
Tự làm thử
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Đọc các đầu vào
String emailRecipient = scanner.nextLine();
String phoneNumber = scanner.nextLine();
String message = scanner.nextLine();
// TODO: Dùng Messenger.formatMessage() để định dạng tin nhắn và lưu lại
// TODO: Tạo EmailMessenger với địa chỉ email người nhận
// TODO: Tạo SMSMessenger với số điện thoại
// TODO: Gọi sendWithTimestamp() trên EmailMessenger với tin nhắn đã định dạng
// TODO: Gọi sendWithTimestamp() trên SMSMessenger với tin nhắn đã định dạng
}
}
Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.
Tất cả bài học trong Lập trình hướng đối tượng
1Kiến thức cơ bản về lập trình hướng đối tượng
Tệp bên ngoàiGiới thiệu về lập trình hướng đối tượngLớp và đối tượngTừ khóa thisPhương thứcTrường (thuộc tính)Phương thức khởi tạoNạp chồng phương thức khởi tạoÔn tập: Máy tính đơn giản4Kế thừa
Kế thừa cơ bản (extends)Từ khóa superGhi đè phương thức (@Override)Chuỗi gọi hàm khởi tạoLớp ObjectKế thừa đơn và đa cấpVì sao không hỗ trợ kế thừa nhiều lớpÔn tập: Phân cấp lớp Employee7Phương thức đặc biệt và lớp Object
Phương thức toString()equals() và hashCode()Phương thức clone()compareTo() và ComparableGiao diện ComparatorÔn tập: sắp xếp tùy chỉnh2Bộ điều chỉnh quyền truy cập và đóng gói
Tổng quan về các mức truy cậpPhương thức getter và setterẨn thông tinTừ khóa finalÔn tập: Trình quản lý tài khoản ngân hàng5Tính đa hình
Kiến thức cơ bản về nạp chồng phương thứcGhi đè phương thức (thời gian chạy)Chuyển kiểu lên và chuyển kiểu xuốngToán tử instanceofLớp và phương thức trừu tượngÔn tập: máy tính hình học8Khái niệm OOP nâng cao
Kết hợp và kế thừaKết tập và hợp thànhLớp bên trong, lớp lồng nhau và lớp ẩn danhKiểu enum và phương thức enumBản ghi (Java 16+)Lớp sealed (Java 17+)3Thuộc tính lớp và thành viên tĩnh
Biến của instance và biến tĩnhPhương thức tĩnhKhối tĩnhHằng số (static final)Ôn tập: bộ đếm và tiện ích6Giao diện và lớp trừu tượng
Giới thiệu về giao diệnTriển khai giao diệnTriển khai nhiều giao diệnPhương thức mặc định và tĩnh trong giao diệnLớp trừu tượng và giao diệnGiao diện hàmÔn tập: hệ thống thanh toán9Kiểu tổng quát
Giới thiệu về kiểu tổng quátLớp tổng quátPhương thức tổng quátTham số kiểu có giới hạnKý tự đại diện (?, extends, super)Ôn tập: vùng chứa tổng quát12Mẫu thiết kế, phần 2
Mẫu CommandMẫu AdapterMẫu DecoratorMẫu Template MethodMẫu StateMẫu CompositeMẫu IteratorTự luyện tập: Trình biên dịch Java online