Search code examples
javagenericscomposition

The scalability of the composite pattern when generics are used


Imagine the following object hierarchy of types:

Group
  Person
    Address

And then some class implementations:

ImmutableGroup
  PeopleyPerson
  MonsterPerson
    PostalAddress
      getZip() :: String
    EmailAddress
      getDomain() :: String

We want to allow clients of this API to use the types in a typesafe manner. So a client may want to do:

group.personAt(0).getAddress().getDomain()

And they can do that because Group is defined as:

Group<? extends PeopleyPerson<EmailAddress>> group

This means Group has to be defined as:

interface Group<A extends Address,P extends Person<A>>

We've had to make Group aware of Address even though it doesn't appear in its "runtime" API.

This smells to me. It implies any further addition to the type hierarchy requires all parents to also represent the added type in its generic declaration.

Is there a way around this?


Solution

  • It should be enough to have

    interface Group<P extends Person<?>>
    

    and then define the actual group instance using concrete types in the hierarchy of composition:

    Group<PeopleyPerson<EmailAddress>> group
    

    This way the consumer of the API will have type safety on the types used while maintaining each interface in the hierarchy (e.g. Group, Person, Address) agnostic of types beyond their immediate children.

    See an example of such an implementation here