0

I have a Java class Book.

public class Book() {
    private List<Horror> horrorBooks;
    private List<Comedy> funnyBooks;
    
    public Book(List<Horror> horrorBooks) {
        this.horrorBooks = CollectionUtils.isNotEmpty(horrorBooks) ? horrorBooks : new ArrayList<>           ();
    }

}

I am now trying to add an additional constructor that will do the same thing but for List funnyBooks

public class Book() {
    private List<Horror> horrorBooks;
    private List<Comedy> funnyBooks;
    
    public Book(List<Horror> horrorBooks) {
        this.horrorBooks = CollectionUtils.isNotEmpty(horrorBooks) ? horrorBooks : new ArrayList<>           ();
    }

    public Book(List<Comedy> funnyBooks) {
        this.funnyBooks = CollectionUtils.isNotEmpty(funnyBooks) ? funnyBooks : new ArrayList<>           ();
    }


}

I am getting a compile error stating that both methods have same erasure

What is the most elegant way to do this? Having two constructors for the same class but one for horrorBooks and one for funnyBooks?

I was thinking I can add if / else logic but this seems like it is not the best approach to achieve what I want.

Kyle
  • 13
  • 3
  • 1
    Does this answer your question? [Method has the same erasure as another method in type](https://stackoverflow.com/questions/1998544/method-has-the-same-erasure-as-another-method-in-type) – Vedant Terkar Dec 01 '22 at 17:43
  • 1
    Perhaps a duplicate of https://stackoverflow.com/questions/10937889/java-how-to-deal-with-type-erasure-in-constructors ? – hooknc Dec 01 '22 at 17:43
  • 1
    It seems kind of strange to me that you're creating a (single) new instance of `Book` given a list of presumably more `Book`s. Perhaps there's a better solution to your problem? – Jesse Dec 01 '22 at 17:44
  • 1
    If `Horror implements Book` and `Comedy implements Book`, then why not simply accept a `List`? You can build filters like `List findHorror() { return books.stream().filter(b -> b instanceof Horror).collect(Collectors.toList()); }` – Rogue Dec 01 '22 at 17:50
  • Will the `Horror` and `Comedy` classes actually be different? Will they have different methods, or different API contracts? If it's purely an organizational thing, I would suggest instead having just a single `Book` class, with a field that contains `enum Genre { HORROR, COMEDY }` (or just maintain separate collections per genre, or some other organizational structure). The big thing is that inheritance is about encapsulation and reuse, not about "how do I want to carve up the data". What if you later want short stories vs novels? – yshavit Dec 01 '22 at 18:04

1 Answers1

0

You need to have one constructor like this:

public Book(List<?> books) {
   
}

Then you can loop through the books in the list and check what kind of book they are.

Another option is to rename your existing class to something more descriptive (e.g. BookCollection) and create a separate Book class that has a genre field and allow passing in a List<Book>, then you can check if (book.getGenre() == comedy) { // append to comedyBooks }, etc.

See similar question here - https://stackoverflow.com/a/21557178/9638991

kimbo
  • 2,513
  • 1
  • 15
  • 24
  • 2
    If there is a common interface (e.g. `Book`), then a `List extends Book>` may be preferrable. – Rogue Dec 01 '22 at 18:01
  • is there a method from List that I can use to check the generic? If I want to see if the generic is type Horror or comedy? i.e books.getClass()? This returns List i believe. I want it to return the type of generic i.e. Horror – Kyle Dec 01 '22 at 18:02
  • There’s not a method for that, but you can just check the first object in the list as in this answer: https://stackoverflow.com/a/16745403/9638991 – kimbo Dec 01 '22 at 18:06