метод equals () для классов с двунаправленной ассоциацией

#java #equals #bidirectional

#java #равно #двунаправленный

Вопрос:

Я пытаюсь реализовать equals метод для классов Java Book и Chapter в моем приложении. Book имеет набор Chapter s, в то время как a Chapter имеет связанный Book . Двунаправленная связь показана следующим образом:

 class Book{
    private String isbn;
    private String name;
    private Date publishDate;
    private Set<Chapter> chapters;
    ...

    public boolean equals(Object o){
        if(o == this){
            return true;
        }
        if (!(o instanceof Book)){
            return false;
        }
        Book book = (Book)o;
        if( (this.isbn.equals(book.getIsbn()) ) amp;amp; (this.name.equals(book.getName())) amp;amp;(this.publishDate.equals(book.getPublishDate())) amp;amp;(this.chapters.equals(book.getChapters())) ){
            return true;
        }else{
            return false;
        }

    }
}
  

Теперь я попытался реализовать equals для Chapter :

 public class Chapter {
    private String title;
    private Integer noOfPages;
    private Book book;
    ...

    public boolean equals(Object o){
         if(o == this){
            return true;
        }
        if (!(o instanceof Chapter)){
            return false;
        }
        Chapter ch = (Chapter)o;
        if((this.title.equals(book.getTitle())) amp;amp; (this.noOfPages.intValue()== book.getNoOfPages().intValue())  ){
            return true;
        }else{
            return false;
        }
    }

}
  

Здесь мне интересно, нужно ли мне также сравнивать поле book. Разве это не запустило бы бесконечный цикл? Каков правильный способ реализации equals метода для таких двунаправленных ассоциаций?

Ответ №1:

Книга должна быть равна другой книге, только если их ISBN равны. Поэтому реализуйте книгу equals только на основе этого поля.

Для главы — сравните номер главы и владельца Book

Ответ №2:

(Я предполагаю, что это Java) В главе метод class equals вы могли бы просто сравнить ссылки на книги (то есть, используя == , а не equals). При этом сравниваются только ссылки, что позволяет избежать бесконечного цикла. Однако, если вы иногда клонируете книги, этот подход потерпит неудачу.

Еще лучшим способом решения этого конкретного случая было бы сравнить не книги, а их ISBN, поскольку это уникальный идентификатор для книги.

В общем, лучше избегать двунаправленных зависимостей, подобных этой. Один из способов — заставить один из двух классов реализовать интерфейс, чтобы не использовать его напрямую.

Комментарии:

1. Даже если использование интерфейсов предотвращает двунаправленную зависимость между классами, все равно существует двунаправленная зависимость между экземплярами во время выполнения. Поэтому я предлагаю не сравнивать книги (ни по == , ни equals() по), а либо просто игнорировать книги (две идентичные главы из разных книг действительно равны или отличаются?), либо сравнивать идентификатор книги, такой как ISBN.

2. Я полностью согласен, я только что прокомментировал циклическую зависимость, поскольку меня учили избегать их, когда это возможно.

Ответ №3:

С точки зрения моделирования эта глава является частью книги. Итак, хотя у вас есть ссылки в обоих направлениях, книга «сильнее», чем глава.

Когда у вас есть отношения part-of, такие как Book и Chapter, часть (глава) иногда учитывает всю (книгу) при определении equals(). Но не наоборот.

Очевидно, что книга не будет использовать свои главы для определения equals() . В главе может быть использована книга. Это зависит от модели.

Ответ №4:

Вы должны выбрать Book поле в качестве идентификатора (например, ISBN). Затем в Chapter equals вы можете сделать что-то вроде

 book.getISBN().equals(other.book.getISBN())