2010-06-10 35 views
9

Tôi có một giao diện và tôi muốn tất cả mọi người triển khai giao diện này để thực hiện phương thức "bằng" được ghi đè.Thực thi "bằng" trong giao diện

Có cách nào để đảm bảo điều đó xảy ra không?

Cách tôi đoán điều này sẽ xảy ra là lớp thực hiện giao diện của tôi sẽ tự động nhận được bằng từ đối tượng do đó làm cho giao diện hạnh phúc.

+1

Lý do cơ bản của bạn cho điều này là gì? –

+0

Trường hợp cụ thể mà tôi gặp phải khi câu hỏi này xuất hiện; Tôi có một giao diện mà một số lớp được triển khai. Các lớp này được xác định bởi một bộ nhận dạng duy nhất. Vì vậy, nếu hai số nhận dạng giống nhau, các đối tượng sẽ được xem là bằng nhau. Tại một thời điểm tôi đã có danh sách một trong các lớp đó và muốn biết liệu một đối tượng mới đã tồn tại trong danh sách chưa. Tôi nghĩ rằng nó sẽ là thanh lịch để sử dụng List.contains (..) cho kiểm tra này. Nhưng điều đó đòi hỏi rằng tôi có thể chắc chắn rằng bằng được ghi đè. Dễ dàng giải quyết theo các cách khác. Một lớp trừu tượng cũng sẽ hoạt động tốt. – Fredrik

Trả lời

10

Không, bạn chỉ có thể tạo một lớp trừu tượng thay vì một giao diện như thế này:

public abstract class MyApi { 

    public final boolean equals(Object other) { 
    if (other == this) { 
     return true; 
    } 
    if (other instanceof MyApi) { 
     return equals((MyApi)other); 
    } 
    return false; 
    } 

    protected abstract boolean equals(MyApi other); 

} 

hoặc một phiên bản đơn giản hơn:

public abstract class MyApi { 

    public boolean equals(Object other) { 
    throw new UnsupportedOperationException("equals() not overridden: " + getClass()); 
    } 

} 

EDIT (đã thử sau nhận xét từ @CodeConfident, cảm ơn! Không bao giờ giả định rằng nó sẽ hoạt động):

Bạn cũng có thể chỉ cần khai báo equals() trong ab lớp stract (! không trong một giao diện) và do đó che giấu việc thực hiện Object và thực thi một thực hiện mới trong bất kỳ lớp con:

public abstract class MyApi { 

    public abstract boolean equals(Object obj); 

    public abstract int hashCode(); 

} 

Dù sao bạn nên luôn luôn thực hiện equals()hashCode() với nhau để thực hiện hợp đồng.

+0

Nếu bạn đang ủng hộ việc sử dụng một lớp trừu tượng, tại sao không khai báo bằng (Object) là trừu tượng? – ILMTitan

+2

@ilmtitan: bạn không thể khai báo một phương thức trừu tượng được thừa hưởng! –

+0

@ArneBurmeister - Điều này không đúng (ít nhất là bây giờ). Bạn hoàn toàn có thể ghi đè lên một phương thức kế thừa với một phương thức trừu tượng bên trong một lớp trừu tượng. Xem câu trả lời này: https://stackoverflow.com/questions/1718112/tostring-equals-and-hashcode-in-an-interface#answer-1718170 – AjahnCharles

3

No. Bạn có thể thêm nó vào giao diện (và do đó các javadocs), nhưng nếu Object.equals có cùng một chữ ký, bạn không thể có trình biên dịch làm cho chúng ghi đè lên nó.

1

Chỉnh sửa: Có lẽ không phải là ý hay (xem nhận xét từ FarmBoy). Rời khỏi đây vì hậu thế.

Thay vì sử dụng equals(Object obj) từ lớp Object, hãy so sánh chúng với việc triển khai giao diện của bạn.

public interface MyInterface { 
    public boolean equals(MyInterface mi); 
} 

Do đó,

public class MyImplementation implements MyInterface { 
    public boolean equals(MyInterface mi) 
    { 
    if(this == mi) 
     return true; 
    // for example, let's say that each implementation 
    // is like a snowflake...(or something) 
    return false; 
    } 
} 

Và sau đó:

public class Main { 

    public static void main(String[] args) 
    { 
    Object o = new MyImplementation(); 
    MyImplementation mi1 = new MyImplementation(); 
    MyImplementation mi2 = new MyImplementation(); 

    // uses Object.equals(Object) 
    o.equals(mi1); 
    // uses MyImplementation.equals(MyInterface) 
    mi1.equals(mi2); 
    // uses Object.equals(Object) 
    mi2.equals(o); 
    } 
} 
+2

Đây không phải là một ý tưởng hay. Bất cứ thứ gì gọi bằng (như đặt một đối tượng vào một 'Set' sẽ không gọi nó bằng, nhưng là 'thực'. Vì vậy, bạn sẽ buộc lớp thực hiện triển khai thực hiện phương thức này, và bất kỳ lập trình viên giỏi nào cũng sẽ triển khai thực hiện –

+0

Điểm tốt - Tôi đã không nghĩ về điều đó.Tôi muốn biết thêm chi tiết từ người hỏi về động cơ đằng sau câu hỏi này. – Catchwa

0

Tôi đoán có thể có hai lý do tại sao như vậy một phương thức equals thể được yêu cầu

  1. Bạn muốn để đảm bảo rằng tất cả các lớp trong ứng dụng của bạn (hoặc một tập hợp con của chúng) "sẽ" có phương thức bằng. Một cái gì đó giống như thực thi tiêu chuẩn, hoặc đảm bảo một số API bạn sử dụng làm việc như họ cần (và họ mong đợi bằng được thực hiện đúng. Nói rằng bạn sử dụng Maps khá nhiều và muốn chắc chắn rằng một tập hợp con của các lớp chắc chắn là có thể phím) Nếu đúng như vậy, đây không phải là cách để đi. Trong trường hợp này, bạn sẽ không thể làm điều đó, nhưng ngay cả khi bạn đang có, nó sẽ không chính xác. Bạn nên đi cho các công cụ bảo hiểm mã, và thử nghiệm đơn vị tốt hơn.

  2. Bạn không muốn phương thức bằng, nhưng muốn có phương pháp tương tự. Trong trường hợp này, bạn có thể tạo một phương thức khác có tên tương tự trong giao diện.

3

No. Giao diện là một hợp đồng đảm bảo rằng các phương pháp tồn tại.

Không có cơ chế nào để thực thi các phương thức đó phải được ghi đè trong giao diện.

0

Tôi đã thử nghiệm bằng cách viết hợp đồng được yêu cầu cho equals trong JavaDoc. Nhưng yêu cầu rằng hashCode phù hợp với equals kết quả trong một hợp đồng rất phức tạp cho hashCode. Vì vậy, tôi đã từ bỏ và tạo ra lớp cơ sở trừu tượng với một thực hiện final của hai phương pháp thay thế.

Các vấn đề liên quan