Chúng ta có nên @Override thực hiện phương thức của giao diện không?


431

Có nên chú thích một phương thức thực hiện một phương thức giao diện @Overridekhông?

Các javadoc của Overridechú thích nói:

Chỉ ra rằng một khai báo phương thức được dự định để ghi đè một khai báo phương thức trong một siêu lớp. Nếu một phương thức được chú thích với loại chú thích này nhưng không ghi đè phương thức siêu lớp, thì trình biên dịch được yêu cầu để tạo thông báo lỗi.

Tôi không nghĩ rằng một giao diện về mặt kỹ thuật là một siêu lớp. Hoặc là nó?

Question Elaboration


5
wow câu hỏi này có thể ngắn hơn, nhưng đó là câu hỏi tôi cần. Cảm ơn
Dan Rosenstark

1
Tôi không thể tìm thấy sự thay thế cho bài viết @Override (Oracle đã chuyển các blog Sun cũ gần đây). Bạn có biết làm thế nào để tìm thấy nó?
Bill Lizard

4
Chúng ta nên có một chú thích @Im Hiện (s) vào lúc này (2015). Điều đó sẽ làm cho mọi thứ rõ ràng!
Alex

3
đến bây giờ (2015) chúng ta có nên sử dụng @Override với java 8 không?
Lorenzo Sciuto

Câu trả lời:


304

Bạn nên sử dụng @Override bất cứ khi nào có thể. Nó ngăn ngừa những sai lầm đơn giản được thực hiện. Thí dụ:

class C {
    @Override
    public boolean equals(SomeClass obj){
        // code ...
    }
}

Điều này không biên dịch bởi vì nó không ghi đè đúng public boolean equals(Object obj).

Điều tương tự cũng sẽ xảy ra đối với các phương thức triển khai giao diện (chỉ 1.6 trở lên ) hoặc ghi đè phương thức của Super class.


150
Lưu ý rằng bạn không thể thêm chú thích @Override vào phương thức triển khai giao diện trong Java 5 - nó tạo ra lỗi. Nó được cho phép trong Java 6.
Bill Michell

17
Ừm, không, không. Trong thực tế, Eclipse tự động chèn @Override khi điền vào các phương thức triển khai giao diện.
jjnguy

14
-1 cho đến khi câu trả lời bao gồm một đề cập về các hành vi khác nhau từ Java 1.5 đến 1.6 liên quan đến việc thực hiện một phương thức giao diện. Chỉ vì tôi đã thấy nó là một khía cạnh khó hiểu cho mọi người và nó thực sự đáng được đề cập.
Grundlefleck

2
Nếu nhật thực phàn nàn thì hãy nâng cấp ur jdk lên> 1.5 và thay đổi mức độ tuân thủ của trình biên dịch thành 1.6 hoặc 1.7. Để làm điều đó, nhấp chuột phải vào dự án của bạn-> thuộc tính-> Trình biên dịch Java và chọn một trình biên dịch cao hơn 1,5.
Hoa hồng

1
Bất cứ ai cũng có thể nghĩ về một ví dụ thực sự biện minh cho câu trả lời (thực hiện các giao diện thay vì ghi đè các phương thức cơ sở)? Một điểm cộng lớn đối với tôi là nó hỗ trợ người đọc kỳ vọng về cách thức và phương thức cụ thể có thể được sử dụng.
Joe Lee-Moyet

103

Tôi tin rằng hành vi javac đã thay đổi - với 1.5 nó đã cấm chú thích, với 1.6 thì không. Chú thích cung cấp một kiểm tra thời gian biên dịch bổ sung, vì vậy nếu bạn đang sử dụng 1.6 tôi sẽ thực hiện.


1
Kiểm tra thêm là gì?
Michael Carman

17
@Michael Bạn có thể nhận thấy nếu bất kỳ giao diện nào đã bị xóa.
Sanghyun Lee

68

Bạn phải luôn chú thích các phương thức @Overridenếu có.

Trong JDK 5, điều này có nghĩa là ghi đè các phương thức của siêu lớp, trong JDK 6 và 7, nó có nghĩa là ghi đè các phương thức của siêu lớp và thực hiện các phương thức giao diện. Lý do, như đã đề cập trước đây, là nó cho phép trình biên dịch bắt lỗi trong đó bạn nghĩ rằng bạn đang ghi đè (hoặc thực hiện) một phương thức, nhưng thực sự đang xác định một phương thức mới (chữ ký khác).

Các equals(Object)so với equals(YourObject)ví dụ là một trường hợp tiêu chuẩn tại điểm, nhưng lập luận tương tự có thể được thực hiện cho triển khai giao diện.

Tôi tưởng tượng lý do không bắt buộc phải chú thích các phương thức triển khai giao diện là vì JDK 5 đã đánh dấu đây là lỗi biên dịch. Nếu JDK 6 thực hiện chú thích này là bắt buộc, nó sẽ phá vỡ tính tương thích ngược.

Tôi không phải là người dùng Eclipse, nhưng trong các IDE khác (IntelliJ), @Overridechú thích chỉ được thêm vào khi thực hiện các phương thức giao diện nếu dự án được đặt là dự án JDK 6+. Tôi sẽ tưởng tượng rằng Eclipse là tương tự.

Tuy nhiên, tôi muốn thấy một chú thích khác cho cách sử dụng này, có thể là một @Implementschú thích.



11

JDK 5.0 không cho phép bạn sử dụng @Overridechú thích nếu bạn đang triển khai phương thức được khai báo trong giao diện (lỗi biên dịch của nó), nhưng JDK 6.0 cho phép nó. Vì vậy, có thể bạn có thể cấu hình sở thích dự án của bạn theo yêu cầu của bạn.


4

Nếu một lớp cụ thể không ghi đè một phương thức trừu tượng, sử dụng @Overrideđể thực hiện là một vấn đề mở vì trình biên dịch sẽ luôn cảnh báo bạn về bất kỳ phương thức chưa được thực hiện nào. Trong những trường hợp này, một đối số có thể được đưa ra rằng nó làm giảm khả năng đọc - đó là nhiều thứ để đọc trên mã của bạn và, ở mức độ thấp hơn, nó được gọi @Overridevà không @Implement.


3

Ghi đè các phương thức của riêng bạn được kế thừa từ các lớp của riêng bạn thường sẽ không phá vỡ các phép tái cấu trúc bằng cách sử dụng ide. Nhưng nếu bạn ghi đè một phương thức được kế thừa từ thư viện thì nên sử dụng nó. Nếu bạn không làm như vậy, bạn sẽ thường không gặp lỗi trong lần thay đổi thư viện sau này, nhưng là một lỗi ẩn rất tốt.


3

Đó không phải là vấn đề với JDK. Trong Helios Eclipse, nó cho phép chú thích @Override cho các phương thức giao diện đã triển khai, bất kể JDK 5 hay 6. Đối với Eclipse Galileo, chú thích @Override không được phép, bất kể JDK 5 hay 6.


2

Đối với tôi, thường thì đây là lý do duy nhất một số mã yêu cầu Java 6 để biên dịch. Không chắc nó có đáng không.


2

Bằng cách đọc javadoc trong java8, bạn có thể tìm thấy phần sau tại phần khai báo Giao diện ghi đè:

Nếu một phương thức được chú thích với trình biên dịch loại chú thích này được yêu cầu để tạo thông báo lỗi trừ khi có ít nhất một trong các điều kiện sau:

  • Phương thức này ghi đè hoặc thực hiện một phương thức được khai báo trong một siêu kiểu.
  • Phương thức có chữ ký tương đương với ghi đè của bất kỳ phương thức công khai nào được khai báo trong {@linkplain Object}.

Vì vậy, ít nhất là trong java8, bạn nên sử dụng @Override khi triển khai phương thức giao diện.


1

Chính Eclipse sẽ thêm @Overridechú thích khi bạn bảo nó "tạo các phương thức chưa thực hiện" trong khi tạo một lớp thực hiện một giao diện.


1

Vấn đề bao gồm cả @Overridelà nó khiến bạn nghĩ rằng bạn quên gọi super.theOverridenMethod()phương thức, điều này rất khó hiểu . Điều này nên rõ ràng. Có lẽ Java nên cung cấp một @Interfaceđược sử dụng ở đây. Ồ, còn một đặc điểm khác của Java ...


3
Gọi một siêu, khi không thực hiện một giao diện, không phải là điều bạn luôn cần hoặc muốn làm. Đôi khi, bạn đang thêm chức năng - vì vậy bạn gọi nó. Những lần khác, bạn đang thay thế chức năng, vì vậy bạn không gọi nó. Một tác giả API nên ghi lại liệu nó có phụ thuộc vào chức năng nội bộ hay không và tạo một hợp đồng tài liệu về cách lớp có thể được mở rộng đúng cách.
lilbyrdie

1

Trong java 6 và các phiên bản mới hơn, bạn có thể sử dụng @Overridecho phương thức triển khai giao diện.

Nhưng, tôi không nghĩ nó có ý nghĩa: ghi đè có nghĩa là bạn có một phương thức trong siêu lớp và bạn đang thực hiện nó trong lớp phụ.

Nếu bạn đang thực hiện một giao diện, tôi nghĩ chúng ta nên sử dụng @Implementhoặc một cái gì đó khác, nhưng không phải @Override.


0

Đối với giao diện, sử dụng @Override gây ra lỗi biên dịch. Vì vậy, tôi đã phải loại bỏ nó.

Thông báo lỗi đã đi " The method getAllProducts() of type InMemoryProductRepository must override a superclass method".

Nó cũng đọc " One quick fix available: Remove @Override annotation."

Đó là trên Eclipse 4.6.3, JDK 1.8.0_144.


0

Nếu lớp đang triển khai interfacelà một abstractlớp, @Overridesẽ hữu ích để đảm bảo rằng việc triển khai là cho một interfacephương thức; không @Overrideabstractlớp sẽ chỉ biên dịch tốt ngay cả khi chữ ký phương thức thực hiện không khớp với phương thức được khai báo trong interface; interfacephương pháp không khớp sẽ vẫn không được thực hiện. Tài liệu Java được trích dẫn bởi @Zhao

Phương thức này ghi đè hoặc thực hiện một phương thức được khai báo trong một siêu kiểu

rõ ràng là đề cập đến một abstractsiêu hạng; một interfacekhông thể được gọi là siêu kiểu. Vì vậy, @Overridelà dư thừa và không hợp lý cho interfaceviệc triển khai phương thức trong các lớp cụ thể.

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.