JavaRush /Blog Java /Random-VI /Nghỉ giải lao #140. Các lớp và giao diện trừu tượng trong...

Nghỉ giải lao #140. Các lớp và giao diện trừu tượng trong Java

Xuất bản trong nhóm
Nguồn: InfoWorld Hôm nay bạn sẽ tìm hiểu trong trường hợp nào nhà phát triển nên sử dụng lớp trừu tượng và trong trường hợp nào nên sử dụng giao diện. Chúng tôi cũng sẽ xác định sự khác biệt giữa các thành phần này của ngôn ngữ Java và cách sử dụng chúng trong các chương trình. Nghỉ giải lao #140.  Các lớp và giao diện trừu tượng trong Java - 1Các lớp và giao diện trừu tượng khá phổ biến trong mã Java và thậm chí trong chính Bộ công cụ phát triển Java (JDK). Mỗi yếu tố này phục vụ một mục đích khác nhau:
  • Giao diện là một cấu trúc trong ngôn ngữ Java giúp triển khai các phương thức trừu tượng và các hằng tĩnh.
  • Các lớp trừu tượng tương tự như các lớp thông thường, ngoại trừ việc chúng có thể bao gồm các phương thức trừu tượng, nghĩa là các phương thức không có phần thân. Các lớp trừu tượng không thể được tạo ra.
Nhiều nhà phát triển cho rằng giao diện và lớp trừu tượng tương tự nhau, nhưng trên thực tế điều này không hoàn toàn đúng. Chúng ta hãy xem xét sự khác biệt chính giữa chúng.

Giao diện là gì

Về cốt lõi, giao diện là một hợp đồng, do đó, việc xác định mục đích tạo ra nó phụ thuộc vào việc triển khai. Giao diện không thể sử dụng các biến đối tượng có thể thay đổi, nó chỉ có thể sử dụng các biến cuối cùng.

Khi nào nên sử dụng giao diện

Các giao diện rất hữu ích để phân tách mã và triển khai tính đa hình. Chúng ta có thể thấy điều này trong JDK với giao diện List :
public interface List<E> extends Collection<E> {

    int size();
    boolean isEmpty();
    boolean add(E e);
    E remove(int index);
    void clear();
}
Như bạn có thể đã nhận thấy, đoạn mã này, mặc dù ngắn gọn, nhưng lại mang tính mô tả khá cao. Chúng ta có thể dễ dàng thấy chữ ký phương thức sẽ được sử dụng để triển khai các phương thức trong giao diện bằng lớp cụ thể. Giao diện List chứa một hợp đồng có thể được triển khai bởi ArrayList , Vector , LinkedList và các lớp khác. Để sử dụng tính đa hình, chúng ta chỉ cần khai báo loại biến bằng cách sử dụng Danh sách và sau đó chọn bất kỳ phiên bản nào có sẵn. Đây là một ví dụ khác:
List list = new ArrayList();
System.out.println(list.getClass());

 List list = new LinkedList();
 System.out.println(list.getClass());
Đầu ra là:
lớp java.util.ArrayList lớp java.util.LinkedList
Trong trường hợp này, các phương thức triển khai cho ArrayList , LinkedListVector là khác nhau, đây là một kịch bản tuyệt vời để sử dụng giao diện. Nếu bạn nhận thấy rằng nhiều lớp thuộc về một lớp cha có cùng các hành động phương thức nhưng hành vi khác nhau. Trong những tình huống như vậy, nên sử dụng giao diện. Tiếp theo, chúng ta hãy xem xét một số tùy chọn để sử dụng giao diện.

Ghi đè phương thức giao diện

Như chúng ta đã biết, giao diện là một loại hợp đồng phải được thực hiện bởi một lớp cụ thể. Các phương thức giao diện hoàn toàn trừu tượng và yêu cầu triển khai lớp cụ thể. Đây là một ví dụ:
public class OverridingDemo {
  public static void main(String[] args) {
    Challenger challenger = new JavaChallenger();
    challenger.doChallenge();
  }
}

interface Challenger {
  void doChallenge();
}

class JavaChallenger implements Challenger {
  @Override
  public void doChallenge() {
    System.out.println("Challenge done!");
  }
}
Phần kết luận:
Thử thách đã xong!
Lưu ý rằng các phương thức giao diện hoàn toàn trừu tượng. Điều này có nghĩa là chúng ta không cần phải khai báo rõ ràng chúng là trừu tượng.

Không biến đổi

Một quy tắc khác cần nhớ là một giao diện chỉ có thể chứa các biến không đổi. Đây là một ví dụ:
public class Challenger {

  int number = 7;
  String name = "Java Challenger";

}
Ở đây cả hai biến đều ẩn cuối cùngtĩnh . Điều này có nghĩa là chúng không đổi, độc lập với thể hiện và không thể thay đổi. Bây giờ chúng ta sẽ thử thay đổi các biến trong giao diện Challenger , giả sử như thế này:
Challenger.number = 8;
Challenger.name = "Another Challenger";
Điều này sẽ gây ra lỗi biên dịch:
Không thể gán giá trị cho biến cuối cùng 'số' Không thể gán giá trị cho biến cuối cùng 'tên'

Phương thức mặc định

Khi các phương thức mặc định được giới thiệu trong Java 8, một số nhà phát triển nghĩ rằng chúng sẽ giống như các lớp trừu tượng. Tuy nhiên điều này không đúng vì giao diện không thể có trạng thái. Một phương thức mặc định có thể có cách triển khai, nhưng các phương thức trừu tượng thì không. Các phương thức mặc định là kết quả của sự đổi mới với các biểu thức và luồng lambda, nhưng chúng ta phải sử dụng chúng một cách cẩn thận. Phương thức trong JDK sử dụng phương thức mặc định là forEach() , là một phần của giao diện Iterable . Thay vì sao chép mã vào từng triển khai Iterable , chúng ta có thể chỉ cần sử dụng lại phương thức forEach :
default void forEach(Consumer<? super T> action) {
  // Code implementation here...
Bất kỳ triển khai Iterable nào cũng có thể sử dụng phương thức forEach() mà không yêu cầu triển khai phương thức mới. Sau đó chúng ta có thể sử dụng lại mã bằng phương thức mặc định. Hãy tạo phương thức mặc định của riêng chúng ta:
public class DefaultMethodExample {

  public static void main(String[] args) {
    Challenger challenger = new JavaChallenger();
    challenger.doChallenge();
  }

}

class JavaChallenger implements Challenger { }

interface Challenger {

  default void doChallenge() {
    System.out.println("Challenger doing a challenge!");
  }
}
Kết quả:
Người thách đấu đang thực hiện một thử thách!
Đối với các phương thức mặc định, điều quan trọng cần lưu ý là mỗi phương thức như vậy cần phải được triển khai. Phương thức mặc định không thể tĩnh. Bây giờ hãy chuyển sang các lớp trừu tượng.

Bản chất của lớp trừu tượng

Các lớp trừu tượng có thể có trạng thái với các biến thể hiện. Điều này có nghĩa là biến thể hiện có thể được sử dụng và sửa đổi. Đây là một ví dụ:
public abstract class AbstractClassMutation {

  private String name = "challenger";

  public static void main(String[] args) {
    AbstractClassMutation abstractClassMutation = new AbstractClassImpl();
    abstractClassMutation.name = "mutated challenger";
    System.out.println(abstractClassMutation.name);
  }

}

class AbstractClassImpl extends AbstractClassMutation { }
Phần kết luận:
kẻ thách thức đột biến

Các phương thức trừu tượng trong các lớp trừu tượng

Giống như các giao diện, các lớp trừu tượng có thể có các phương thức trừu tượng. Một phương thức trừu tượng là một phương thức không có phần thân. Không giống như các giao diện, các phương thức trừu tượng trong các lớp trừu tượng phải được khai báo rõ ràng là trừu tượng. Đây là một ví dụ:
public abstract class AbstractMethods {

  abstract void doSomething();

}
Và đây là nỗ lực khai báo một phương thức mà không cần triển khai và không có từ khóa trừu tượng :
public abstract class AbstractMethods {
   void doSomethingElse();
}
Thật không may, nó dẫn đến lỗi biên dịch:
Thiếu nội dung phương thức hoặc khai báo trừu tượng

Khi nào nên sử dụng các lớp trừu tượng

Lớp trừu tượng được khuyên dùng khi bạn cần triển khai trạng thái có thể thay đổi. Ví dụ: Khung công tác sưu tập Java bao gồm một lớp Tóm tắt danh sách sử dụng trạng thái của các biến. Trong trường hợp bạn không cần duy trì trạng thái lớp, tốt hơn nên sử dụng giao diện.

Sự khác biệt giữa các lớp trừu tượng và giao diện

Từ góc độ lập trình hướng đối tượng, sự khác biệt chính giữa giao diện và lớp trừu tượng là giao diện không thể có trạng thái, trong khi lớp trừu tượng có thể có trạng thái với các biến thể hiện. Một điểm khác biệt chính là các lớp có thể triển khai nhiều giao diện nhưng chúng chỉ có thể mở rộng một lớp trừu tượng. Giải pháp này dựa trên thực tế là đa kế thừa (mở rộng nhiều hơn một lớp) có thể dẫn đến bế tắc mã. Các nhà phát triển ngôn ngữ Java đã quyết định tránh điều này. Một điểm khác biệt nữa là các giao diện có thể được triển khai theo lớp hoặc được mở rộng bằng giao diện, nhưng các lớp chỉ có thể được mở rộng. Điều quan trọng cần lưu ý là biểu thức lambda chỉ có thể được sử dụng với giao diện chức năng (nghĩa là giao diện chỉ có một phương thức), trong khi các lớp trừu tượng chỉ có một phương thức trừu tượng không thể sử dụng biểu thức lambda. Dưới đây là một số khác biệt nữa giữa các lớp trừu tượng và giao diện. Giao diện:
  • Chỉ có thể có các biến tĩnh cuối cùng. Một giao diện không bao giờ có thể thay đổi trạng thái của chính nó.
  • Một lớp có thể thực hiện nhiều giao diện.
  • Có thể được thực hiện bằng cách sử dụng từ khóa thực hiện. Một giao diện có thể mở rộng một giao diện khác.
  • Các phương thức chỉ có thể sử dụng các trường, tham số hoặc biến cục bộ cuối cùng tĩnh.
  • Chỉ các giao diện chức năng mới có thể sử dụng hàm lambda trong Java.
  • Không thể có một hàm tạo.
  • Có thể có các phương pháp trừu tượng.
  • Có thể có các phương thức mặc định và tĩnh (được giới thiệu trong Java 8).
  • Có thể có các phương thức riêng khi triển khai (được giới thiệu trong Java 9).
Các lớp trừu tượng:
  • Có thể có bất kỳ biến thể hoặc biến tĩnh nào, có thể thay đổi hoặc không thay đổi.
  • Một lớp chỉ có thể mở rộng một lớp trừu tượng.
  • Có thể có một phiên bản của các trường, tham số hoặc biến cục bộ có thể thay đổi.
  • Các lớp trừu tượng chỉ có một phương thức trừu tượng không thể sử dụng biểu thức lambda.
  • Có thể có một hàm tạo.
  • Có thể có bất kỳ phương pháp nào.
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION