Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Appropriate way to subclass Guava's ImmutableSet

Tags:

java

guava

I have a class along the lines of

class Receipt
{
     private Set<Order> orders;
     public Receipt(Set<Order> orders)
     {
         this.orders = ImmutableSet.copyOf(orders)
     }   
}

This has served me well.

However, because of some type-erasure & persistence issues I'm facing, I'd like to now introduce a form of

class OrderSet extends Set<Order> {}

Obviously I can't extend Set<Order>, as it's an interface. I'd like to keep my implementation as immutable. However, I can't extend ImmutableSet<Order>, as the docs state:

Note: Although this class is not final, it cannot be subclassed outside its package as it has no public or protected constructors. Thus, instances of this type are guaranteed to be immutable.

I could use composition, giving OrderSet a backing collection of ImmutableSet and delegate all the Set methods to it. However, this seems overkill.

Is there another way I can achieve a non-generic subclass here?

like image 753
Marty Pitt Avatar asked Feb 02 '12 11:02

Marty Pitt


1 Answers

No, composition isn't overkill, it's exactly the way to go.

You should create your OrderSet as follows because, as Louis emphasizes in the comments, this use case is exactly what they're meant for:

public class OrderSet extends ForwardingSet<Order> {
  private final ImmutableSet<Order> orders;
  public class OrderSet (Set<Order> orders) {
    this.orders = ImmutableSet.copyOf(orders);
  }
  protected ImmutableSet<Order> delegate() { return orders; }
}

The immutable classes in Guava are designed so that you don't extend them. You have to use composition and it's precisely the right way to go.

like image 79
Olivier Grégoire Avatar answered Nov 14 '22 17:11

Olivier Grégoire