Các phương thức trong giao diện Java nên được khai báo có hoặc không có công cụ sửa đổi truy cập công cộng?


292

Các phương thức trong giao diện Java nên được khai báo có hoặc không có công cụ publicsửa đổi truy cập?

Về mặt kỹ thuật, nó không thành vấn đề, tất nhiên. Một phương thức lớp thực hiện interfaceluôn là một public. Nhưng một quy ước tốt hơn là gì?

Bản thân Java không nhất quán trong việc này. Xem ví dụ Collectionso với Comparable, hoặc Futureso với ScriptEngine.


22
Thật tệ vì viết nó như là công khai ngụ ý rằng nó thể không công khai
Pacerier

8
Bạn nên tránh cú pháp dư thừa của bất kỳ hình thức.
Hầu tước Lorne

3
@Pacerier, trong khi tôi đồng ý rằng thật tệ khi sử dụng publictrong ngữ cảnh này, các phương thức giao diện mặc định bây giờ có thể là riêng tư (với java 9). Tôi đề nghị bạn xóa bình luận của bạn vì nó đã lỗi thời.
aioobe

2
Đúng, mọi thứ có thể thay đổi trong Java 9. "Viết nó dưới dạng công khai ngụ ý rằng nóthể không công khai" . Vì chính xác điều đó dường như là có thể có trong Java 9, nên đối số này bây giờ có lợi cho việc thực sự viết ra public.
MC Hoàng đế

Câu trả lời:


334

Các JLS làm rõ điều này:

Điều đó được cho phép, nhưng không được khuyến khích vì vấn đề phong cách, chỉ định một cách thừa thãi publicvà / hoặc công cụ abstractsửa đổi cho một phương thức được khai báo trong giao diện.


6
Liên kết JLS ở trên là dành cho Java 7 tại thời điểm tôi đọc nó. Sau khi nhận xét về Java 9 cho phép các phương thức không công khai, tôi chỉ muốn xác nhận rằng từ ngữ tương tự vẫn còn đó cho SE9 JLS . ( publicmột phần là như nhau, and/or abstractmột phần đã bị loại bỏ)
OzgurH

3
Vẫn đúng trong SE11 JLS
Ortomala Lokni


44

Công cụ sửa đổi công khai nên được bỏ qua trong các giao diện Java (theo ý kiến ​​của tôi).

Vì nó không thêm bất kỳ thông tin bổ sung nào, nó chỉ thu hút sự chú ý khỏi những thứ quan trọng.

Hầu hết các hướng dẫn phong cách sẽ khuyên bạn nên bỏ nó đi, nhưng tất nhiên, điều quan trọng nhất là phải nhất quán trên cơ sở mã của bạn và đặc biệt là cho mỗi giao diện. Ví dụ sau đây có thể dễ dàng gây nhầm lẫn cho ai đó, người không thông thạo 100% về Java:

public interface Foo{
  public void MakeFoo();
  void PerformBar();
}

3
Bạn có một liên kết đến một hướng dẫn phong cách như vậy?
Benno Richters

9
Tính nhất quán là điều quan trọng nhất, và là câu trả lời cho 99% các loại câu hỏi này.
SCdF

Đồng ý lại: tính nhất quán. Một cái gì đó cho các tiêu chuẩn mã hóa của bạn tài liệu các bạn :)
JeeBee

2
Bno: Một ví dụ là Đặc tả ngôn ngữ Java, một ví dụ khác là Checkstyle.
Rasmus Faber

9

Mặc dù thực tế là câu hỏi này đã được hỏi từ lâu nhưng tôi cảm thấy một mô tả toàn diện sẽ làm rõ lý do tại sao không cần sử dụng trừu tượng công khai trước các phương thức và chung kết tĩnh trước các hằng số của giao diện.

Trước hết Giao diện được sử dụng để chỉ định các phương thức phổ biến cho một tập hợp các lớp không liên quan mà mỗi lớp sẽ có một triển khai duy nhất. Do đó, không thể chỉ định công cụ sửa đổi truy cập là riêng tư vì các lớp khác không thể bị truy cập để ghi đè.

Thứ hai, Mặc dù người ta có thể khởi tạo các đối tượng của một loại giao diện nhưng một giao diện được nhận ra bởi các lớp thực hiện nó và không được kế thừa. Và vì một giao diện có thể được triển khai (nhận ra) bởi các lớp không liên quan khác nhau không cùng gói, do đó, công cụ sửa đổi truy cập được bảo vệ cũng không hợp lệ. Vì vậy, đối với công cụ sửa đổi truy cập, chúng tôi chỉ còn lại sự lựa chọn công khai.

Thứ ba, một giao diện không có bất kỳ triển khai dữ liệu nào bao gồm các biến và phương thức thể hiện. Nếu có lý do hợp lý để chèn các phương thức được thực hiện hoặc các biến thể hiện trong một giao diện thì nó phải là một siêu lớp trong hệ thống phân cấp kế thừa chứ không phải là một giao diện. Xem xét thực tế này, vì không có phương thức nào có thể được thực hiện trong một giao diện do đó tất cả các phương thức trong giao diện phải trừu tượng.

Thứ tư, Giao diện chỉ có thể bao gồm hằng số là thành viên dữ liệu của nó, điều đó có nghĩa là chúng phải là cuối cùng và tất nhiên các hằng số cuối cùng được khai báo là tĩnh để chỉ giữ một thể hiện của chúng. Do đó, cuối cùng tĩnh cũng là một bắt buộc cho các hằng số giao diện.

Vì vậy, trong kết luận mặc dù sử dụng trừu tượng công khai trước các phương thức và công khai tĩnh cuối cùng trước các hằng số của giao diện là hợp lệ nhưng vì không có tùy chọn nào khác nên nó được coi là dự phòng và không được sử dụng.


7

Với sự ra đời của private, static, defaultbổ cho các phương pháp giao diện trong Java 8/9, mọi thứ trở nên phức tạp hơn và tôi có xu hướng nghĩ rằng tờ khai đầy đủ là dễ đọc hơn (cần Java 9 để biên dịch):

public interface MyInterface {

    //minimal
    int CONST00 = 0;
    void method00();
    static void method01() {}
    default void method02() {}
    private static void method03() {}
    private void method04() {}

    //full
    public static final int CONST10 = 0;
    public abstract void method10();
    public static void method11() {}
    public default void method12() {}
    private static void method13() {}
    private void method14() {}

}

5

Tôi sẽ tránh đặt các sửa đổi được áp dụng theo mặc định. Như đã chỉ ra, nó có thể dẫn đến sự không nhất quán và nhầm lẫn.

Điều tồi tệ nhất tôi thấy là một giao diện với các phương thức được khai báo abstract...


5

Tôi đã sử dụng các phương thức khai báo với công cụ publicsửa đổi, bởi vì nó làm cho mã dễ đọc hơn, đặc biệt là với tô sáng cú pháp. Mặc dù vậy, trong dự án mới nhất của chúng tôi, chúng tôi đã sử dụng Checkstyle hiển thị cảnh báo với cấu hình mặc định cho các publicsửa đổi trên các phương thức giao diện, vì vậy tôi đã chuyển sang sử dụng chúng.

Vì vậy, tôi không thực sự chắc chắn những gì tốt nhất, nhưng một điều tôi thực sự không thích là sử dụng public abstractcác phương thức giao diện. Eclipse thực hiện điều này đôi khi khi tái cấu trúc với "Extract Interface".


2
Nhưng chỉ khi bạn kiểm tra hai hộp kiểm khai báo các phương thức là công khai, trừu tượng.
MetroidFan2002

4

Tôi luôn viết những gì tôi sẽ sử dụng nếu không có giao diện và tôi đang viết một triển khai trực tiếp, tức là tôi sẽ sử dụng public.


6
Bạn cũng sẽ tuyên bố rõ ràng tất cả các phương pháp giao diện trừu tượng?
Dan Dyer

4
Đó là một giao diện, không phải là một lớp trừu tượng. Liên quan đến 'công khai', đó là 7 ký tự mà bạn đã nhập vào thời điểm bạn nghĩ về nó, vấn đề lớn! Và đó cũng là cách nó sẽ được xác định trong quá trình triển khai, đó là +1 cho tính nhất quán cân bằng -1 cho dự phòng.
JeeBee

3

Tôi thích bỏ qua nó, tôi đọc ở đâu đó rằng các giao diện theo mặc định, publicabstract.

Thật ngạc nhiên, cuốn sách - Head First Design Forms , đang sử dụng publicvới phương pháp khai báo giao diện và phương thức giao diện ... khiến tôi phải suy nghĩ lại một lần nữa và tôi đã tìm đến bài đăng này.

Dù sao, tôi nghĩ rằng thông tin dư thừa nên được bỏ qua.


1
Chỉ cần làm rõ, nếu bạn bỏ qua công cụ publicsửa đổi truy cập trên khai báo giao diện thì nó sẽ không được công khai và trừu tượng theo mặc định. docs.oracle.com/javase/tutorial/java/IandI/interfaceDef.html
Jabbslad

3

Tôi không đồng ý với câu trả lời phổ biến, rằng việc công khai ngụ ý rằng có những lựa chọn khác và vì vậy nó không nên ở đó. Thực tế là bây giờ với Java 9 và hơn thế nữa là có các tùy chọn khác.

Tôi nghĩ thay vào đó Java nên thực thi / yêu cầu 'công khai' được chỉ định. Tại sao? Bởi vì sự vắng mặt của công cụ sửa đổi có nghĩa là quyền truy cập 'gói' ở mọi nơi khác và việc này là trường hợp đặc biệt là điều dẫn đến sự nhầm lẫn. Nếu bạn chỉ đơn giản biến nó thành một lỗi biên dịch với một thông báo rõ ràng (ví dụ: "Không cho phép truy cập gói trong một giao diện."), Chúng ta sẽ thoát khỏi sự mơ hồ rõ ràng rằng có tùy chọn bỏ qua giới thiệu 'công khai'.

Lưu ý từ ngữ hiện tại tại: https://docs.oracle.com/javase/specs/jls/se9/html/jls-9.html#jls-9.4

"Một phương thức trong phần thân của một giao diện có thể được khai báo là công khai hoặc riêng tư (§.6.6). Nếu không có công cụ sửa đổi truy cập nào được đưa ra, thì phương thức này hoàn toàn công khai. Nó được cho phép, nhưng không được khuyến khích là chỉ định công khai công cụ sửa đổi cho một khai báo phương thức trong một giao diện. "

Xem rằng 'riêng tư' IS được phép ngay bây giờ. Tôi nghĩ rằng câu cuối cùng đã bị xóa khỏi JLS. Thật không may là hành vi "công khai ngầm" đã từng được cho phép vì giờ đây nó có thể vẫn còn tồn tại cho sự tương thích ngược và dẫn đến sự nhầm lẫn rằng sự vắng mặt của công cụ sửa đổi truy cập có nghĩa là 'công khai' trong các giao diện và 'gói' ở nơi khác.


2

Lý do cho các phương thức trong các giao diện mặc định là công khai và trừu tượng có vẻ khá logic và rõ ràng đối với tôi.

Một phương thức trong một giao diện theo mặc định là trừu tượng để buộc lớp triển khai cung cấp một triển khai và được công khai theo mặc định để lớp triển khai có quyền truy cập để làm như vậy.

Việc thêm các sửa đổi đó vào mã của bạn là không cần thiết và vô dụng và chỉ có thể dẫn đến kết luận rằng bạn thiếu kiến ​​thức và / hoặc hiểu về các nguyên tắc cơ bản của Java.


Nhưng bạn cũng có thể thực hiện các phương thức trừu tượng có quyền truy cập được bảo vệ - trong một lớp trừu tượng. Vì vậy, công chúng không phải là một yêu cầu. Thêm một cái gì đó rõ ràng giống như những gì sẽ là mặc định luôn luôn dư thừa, nhưng nó không phải lúc nào cũng vô dụng.
swpalmer

Nhưng câu hỏi là về giao diện. Tôi không muốn lạc đề. Ý tôi là, kể từ Java 8, chúng ta cũng có thể nói về phương thức riêng tư và mặc định trong các giao diện, phải không? Vì vậy, cuộc thảo luận này có thể được thực hiện khá dài nếu chúng ta muốn. ;)
Iuliana Cosmina

1

Đó là hoàn toàn chủ quan. Tôi bỏ qua công cụ publicsửa đổi dự phòng vì nó có vẻ như lộn xộn. Như đã đề cập bởi những người khác - tính nhất quán là chìa khóa cho quyết định này.

Thật thú vị khi lưu ý rằng các nhà thiết kế ngôn ngữ C # đã quyết định thực thi điều này. Khai báo một phương thức giao diện là công khai trong C # thực sự là một lỗi biên dịch. Tính nhất quán có lẽ không quan trọng đối với các ngôn ngữ, vì vậy tôi đoán điều này không thực sự liên quan trực tiếp đến Java.


-9

Mọi người sẽ học giao diện của bạn từ việc hoàn tất mã trong IDE của họ hoặc trong Javadoc, chứ không phải từ việc đọc nguồn. Vì vậy, không có điểm nào để đưa "công khai" vào nguồn - không ai đọc nguồn này.


8
Tôi thực sự phải không đồng ý với tuyên bố rằng không ai đang đọc nguồn này. Tôi nghĩ rằng nhiều người sử dụng ví dụ F3 trong Eclipse để phóng to mã. Các công cụ như Maven cung cấp tùy chọn tải xuống các nguồn, không chỉ JavaDoc, vì một lý do.
Benno Richters

Đó không phải là lý do chính xác cho việc không thêm công cụ publicsửa đổi truy cập vào giao diện. Đó là bởi thiết kế và sau khi suy nghĩ cẩn thận đằng sau nó.
mtk
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.