2012-04-20 13 views
7

Nếu tôi triển khai equals()hashCode() trong cả lớp cha và con, thì cần phải gọi super.equals() trong equals() trong lớp con, ví dụ:Gọi super.equals và super.hashCode trong lớp con?

public boolean equals(Object obj) { 

    if (obj.getClass() != ChildClass.class) { 
    return false; 
    } 

    return super.equals() && this.var == ((ChildClass) obj).var; 

} 
+0

P.S. Tôi giả định rằng lớp cha không phải là đối tượng và đưa ra định nghĩa đúng của 'equals' và' hashCode'. –

Trả lời

8

Không, điều đó không cần thiết và có thể sẽ sai. Thật vậy, một phần lý do tại sao bạn ghi đè equal là vì super.equals không đưa ra hành vi đúng (phải không?).

Hoặc đặt một cách khác, nếu super.equals mang lại hành vi đúng, có thể bạn không cần phải đi đến sự cố khi ghi đè.

Nhưng nếu bạn ghi đè equals, thì có, bạn cũng cần ghi đè hashCode.

+2

'SuperClass.equals' rõ ràng chỉ có thể so sánh các trường hợp' SuperClass' và không biết gì về 'SubClass'. Đó là lý do tại sao 'SubClass' phải ghi đè lên nó, ngay cả khi nó là hoàn toàn chính xác về' SuperClass'. Nhưng nó sẽ là ngu ngốc để reimplement hành vi của nó trong 'SubClass' (hoặc trong mỗi lớp con) thay vì gọi' super.equals' (trước khi so sánh các phần con), phải không? –

+4

Vâng, nếu bình đẳng giá trị đang được triển khai, có thể cần phải gọi 'super.equals()' để có các trường kế thừa được kiểm tra về bình đẳng ... – Alan

+0

thực sự, nhiều lần bạn chỉ cần thêm kiểm tra cho các trường bổ sung (như @ Alan đã đề cập), do đó, gọi 'super.equals()' là cần thiết. Ngoài ra, nếu bạn chỉ thêm các trường, bạn không _need_ để ghi đè 'hashCode()'. – jtahlborn

2

Nếu siêu lớp học của bạn không thực hiện bằng, super.equals sau đó gọi sẽ giúp bạn thực hiện đối tượng mà chỉ so sánh tài liệu tham khảo, vì vậy trong bất kỳ bình thường bằng thực hiện nơi bạn muốn so sánh một chìa khóa kinh doanh nó sẽ thực sự gây ra rất nhiều âm bản sai.

Điều đó nói rằng, việc triển khai của bạn ở trên thực sự không khác biệt ngữ nghĩa hơn mặc định bằng cách thực hiện trong Đối tượng vì bạn chỉ đang sử dụng == để so sánh.

Đối với hashCode, nếu bạn ghi đè bằng bạn thực sự nên ghi đè hashCode để giữ cho hợp đồng của hai. Ví dụ, nếu bạn đang sử dụng một khóa kinh doanh cho bằng bạn nên có thể sử dụng cùng một khóa kinh doanh cho hashcode để hai đối tượng bằng nhau tạo ra cùng một hashcode.

0

EDIT

Tôi chỉ nhận thấy bạn sử dụng bình đẳng giai cấp, không instanceof - nghĩa là tính phản xạ sẽ là đúng. Trong ví dụ của bạn, việc sử dụng super.equals có lẽ là chính xác, miễn là lớp cha không cung cấp định nghĩa về bình đẳng mà ngược lại với lớp con bạn muốn (ví dụ: Object).

Điểm chính là định nghĩa về bình đẳng phải đến từ chính xác một loại (lớp hoặc giao diện) trong phân cấp lớp của bạn. Nếu việc thực hiện định nghĩa đó tận dụng lợi thế của super.equals, điều đó là tốt.

END EDIT, văn bản gốc bên dưới

Đó là gần như chắc chắn điều sai trái để làm, bởi vì nó sẽ vi phạm sở hữu phản xạ bình đẳng.

Giả sử bạn có Hình dạng và hình dạng đó giống với Hình dạng khác nếu chúng cùng loại: Hình vuông bằng Vuông, Vòng tròn bằng Hình tròn, v.v. Bây giờ bạn mở rộng để tạo một Màu sắc cho phép thêm kiểm tra màu.

Shape shape1 = new Shape(SQUARE); 
Shape shape2 = new ColoredShape(SQUARE, RED); 

Bạn thực hiện ColoredSquare.equals như super.equals(other) && other.color == this.color, như trong câu hỏi của bạn. Nhưng bây giờ, lưu ý rằng shape1.equals(shape2) == true (kể từ shape1 chỉ sử dụng Shape.equals), nhưng shape2.equals(shape1) == false (vì nó thêm kiểm tra màu).

Đạo đức của câu chuyện là việc sử dụng loại bình đẳng tầng này thực sự khó khăn, nếu không phải là không thể. Về cơ bản, bình đẳng nên đến từ chính xác một loại trong phân cấp kiểu của bạn - có thể là Object, loại của bạn, loại siêu hoặc giao diện xác định hợp đồng (ví dụ: trong khung bộ sưu tập, xác định sự bình đẳng cho Set, List, v.v.).

+0

Đạo đức của câu chuyện là thay vì bạn chỉ nên thừa kế từ các lớp trừu tượng, không phải từ các lớp cụ thể. Nó vi phạm quy tắc này gây ra các vấn đề bạn mô tả độc đáo, không gọi 'super.equals' từ phương thức' equals' của lớp con. –

+0

@ PéterTörök Tôi không chắc cách áp dụng, vì lớp trừu tượng vẫn có thể cung cấp 'equals' và' hashCode'. Trong ví dụ của tôi, giả sử 'Shape' là trừu tượng và có hai lớp con,' ColorShape' và 'ColorlessShape', chỉ cái sau mới thêm màu kiểm tra để bình đẳng. Cùng một vấn đề. – yshavit

+0

Không, bởi vì nếu 'Hình dạng' là trừu tượng, bạn không thể có các đối tượng' Shape' đơn giản, chỉ có 'ColorShape's và/hoặc' ColorlessShape's. Và đối với những điều này, bạn có thể thực hiện 'equals' đúng hoặc không sử dụng lại' super.equals'. Bởi vì bạn không bao giờ có thể có một tình huống mà objectOfA * là một * B nhưng objectOfB * không phải là một * A. –

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